2004-10-18 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlTextReader.cs
index b6633645dbf4cd8112ed96322c1a8c7706237b50..f1d5b59e8b04e5f2364e7c63c64d26bd4fe4522d 100644 (file)
@@ -9,29 +9,52 @@
 // (C) 2001, 2002 Jason Diamond  http://injektilo.org/
 //
 
-// FIXME:
 //
-//   I haven't checked whether DTD parser runs correct.
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-//   More strict well-formedness checking should be done.
+
+// FIXME:
 //
-//   NameTables aren't being used completely yet.
+//   Some thought needs to be given to performance.
 //
-//   Some thought needs to be given to performance. There's too many
-//   strings being allocated.
+//   If current node is on an Attribute, Prefix might be null, and
+//   in several fields which uses XmlReader, it should be considered.
 //
 
 using System;
 using System.Collections;
+using System.Globalization;
 using System.IO;
+using System.Security.Policy;
 using System.Text;
 using System.Xml.Schema;
 using Mono.Xml;
-using Mono.Xml.Native;
 
 namespace System.Xml
 {
+#if NET_2_0
+       public class XmlTextReader : XmlReader,
+               IXmlLineInfo, IXmlNamespaceResolver
+#else
        public class XmlTextReader : XmlReader, IXmlLineInfo
+#endif
        {
                #region Constructors
 
@@ -75,8 +98,14 @@ namespace System.Xml
                }
 
                public XmlTextReader (string url, XmlNameTable nt)
-                       : this (url, new XmlStreamReader (url, null, null), nt)
                {
+                       Uri uri = resolver.ResolveUri (null, url);
+                       Stream s = resolver.GetEntity (uri, null, typeof (Stream)) as Stream;
+                       XmlParserContext ctx = new XmlParserContext (nt,
+                               new XmlNamespaceManager (nt),
+                               String.Empty,
+                               XmlSpace.None);
+                       this.InitializeContext (uri.ToString(), ctx, new XmlStreamReader (s), XmlNodeType.Document);
                }
 
                public XmlTextReader (TextReader input, XmlNameTable nt)
@@ -102,7 +131,6 @@ namespace System.Xml
                {
                }
 
-               [MonoTODO("TODO as same as private XmlTextReader(TextReader, XmlNodeType, XmlParserContext)")]
                public XmlTextReader (string xmlFragment, XmlNodeType fragType, XmlParserContext context)
                        : this (context != null ? context.BaseURI : String.Empty,
                                new StringReader (xmlFragment),
@@ -111,8 +139,6 @@ namespace System.Xml
                {
                }
 
-               // TODO still remains as described at head of this file,
-               // but it might not be TODO of the constructors...
                XmlTextReader (string url, TextReader fragment, XmlNodeType fragType, XmlParserContext context)
                {
                        InitializeContext (url, context, fragment, fragType);
@@ -124,7 +150,7 @@ namespace System.Xml
 
                public override int AttributeCount
                {
-                       get { return attributes.Count; }
+                       get { return attributeCount; }
                }
 
                public override string BaseURI
@@ -132,9 +158,32 @@ namespace System.Xml
                        get { return parserContext.BaseURI; }
                }
 
+#if NET_2_0
+               public override bool CanResolveEntity {
+                       get { return true; }
+               }
+
+#endif
+
+               internal bool CharacterChecking {
+                       get { return checkCharacters && normalization; }
+                       set { checkCharacters = value; }
+               }
+
+               // for XmlReaderSettings.CloseInput support
+               internal bool CloseInput {
+                       get { return closeInput; }
+                       set { closeInput = value; }
+               }
+
                public override int Depth
                {
                        get {
+                               int nodeTypeMod = currentToken.NodeType == XmlNodeType.Element  ? 0 : -1;
+                               if (currentAttributeValue >= 0)
+                                       return nodeTypeMod + elementDepth + 2; // inside attribute value.
+                               else if (currentAttribute >= 0)
+                                       return nodeTypeMod + elementDepth + 1;
                                return elementDepth;
                        }
                }
@@ -143,78 +192,77 @@ namespace System.Xml
                {
                        get { return parserContext.Encoding; }
                }
+#if NET_2_0
+               [MonoTODO]
+               public EntityHandling EntityHandling {
+                       get { return entityHandling; }
+                       set { entityHandling = value; }
+               }
+#endif
 
-               public override bool EOF
-               {
-                       get
-                       {
-                               return
-                                       readState == ReadState.EndOfFile ||
-                                       readState == ReadState.Closed;
-                       }
+               public override bool EOF {
+                       get { return readState == ReadState.EndOfFile; }
                }
 
-               public override bool HasValue
-               {
-                       get { 
-                               if (this.valueBuilderAvailable)
-                                       return valueBuilder.Length != 0;
-                               else
-                                       return value != String.Empty;
-                       }
+#if NET_2_0
+               [MonoTODO]
+               public override Evidence Evidence {
+                       get { return base.Evidence; }
                }
+#endif
 
-               public override bool IsDefault
-               {
-                       get
-                       {
-                               // XmlTextReader does not expand default attributes.
-                               return false;
-                       }
+               public override bool HasValue {
+                       get { return cursorToken.Value != null; }
                }
 
-               public override bool IsEmptyElement
-               {
-                       get { return isEmptyElement; }
+               public override bool IsDefault {
+                       // XmlTextReader does not expand default attributes.
+                       get { return false; }
                }
 
-               public override string this [int i]
-               {
+               public override bool IsEmptyElement {
+                       get { return cursorToken.IsEmptyElement; }
+               }
+
+               public override string this [int i] {
                        get { return GetAttribute (i); }
                }
 
-               public override string this [string name]
-               {
+               public override string this [string name] {
                        get { return GetAttribute (name); }
                }
 
-               public override string this [string localName, string namespaceName]
-               {
+               public override string this [string localName, string namespaceName] {
                        get { return GetAttribute (localName, namespaceName); }
                }
 
-               public int LineNumber
-               {
-                       get { return currentInput.LineNumber; }
+               public int LineNumber {
+                       get {
+                               if (useProceedingLineInfo)
+                                       return line;
+                               else
+                                       return cursorToken.LineNumber;
+                       }
                }
 
-               public int LinePosition
-               {
-                       get { return currentInput.LinePosition; }
+               public int LinePosition {
+                       get {
+                               if (useProceedingLineInfo)
+                                       return column;
+                               else
+                                       return cursorToken.LinePosition;
+                       }
                }
 
-               public override string LocalName
-               {
-                       get { return localName; }
+               public override string LocalName {
+                       get { return cursorToken.LocalName; }
                }
 
-               public override string Name
-               {
-                       get { return name; }
+               public override string Name {
+                       get { return cursorToken.Name; }
                }
 
-               public bool Namespaces
-               {
+               public bool Namespaces {
                        get { return namespaces; }
                        set { 
                                if (readState != ReadState.Initial)
@@ -223,81 +271,66 @@ namespace System.Xml
                        }
                }
 
-               public override string NamespaceURI
-               {
-                       get { return namespaceURI; }
+               public override string NamespaceURI {
+                       get { return cursorToken.NamespaceURI; }
                }
 
-               public override XmlNameTable NameTable
-               {
+               public override XmlNameTable NameTable {
                        get { return parserContext.NameTable; }
                }
 
-               public override XmlNodeType NodeType
-               {
-                       get { return nodeType; }
+               public override XmlNodeType NodeType {
+                       get { return cursorToken.NodeType; }
                }
 
-               [MonoTODO]
-               public bool Normalization
-               {
+               public bool Normalization {
                        get { return normalization; }
                        set { normalization = value; }
                }
 
-               public override string Prefix
-               {
-                       get { return prefix; }
+               public override string Prefix {
+                       get { return cursorToken.Prefix; }
                }
 
-               public override char QuoteChar
-               {
-                       get {
-                               // value string holds attribute quotation char.
-                               if (NodeType == XmlNodeType.Attribute)
-                                       return value [0];
-                               else
-                                       return '"';
-                       }
+#if NET_2_0
+               public bool ProhibitDtd {
+                       get { return prohibitDtd; }
+                       set { prohibitDtd = value; }
                }
+#endif
 
-               public override ReadState ReadState
-               {
+               public override char QuoteChar {
+                       get { return cursorToken.QuoteChar; }
+               }
+
+               public override ReadState ReadState {
                        get { return readState; }
                }
 
-               public override string Value
-               {
-                       get {
-                               
-                               string v = value;
-                               if (valueBuilderAvailable)
-                                       v = valueBuilder.ToString ();
-                               if(NodeType == XmlNodeType.Attribute)
-                                       return UnescapeAttributeValue(v);
-                               else
-                                       return v;
-                       }
+#if NET_2_0
+               public override XmlReaderSettings Settings {
+                       get { return base.Settings; }
                }
+#endif
 
-               public WhitespaceHandling WhitespaceHandling
-               {
+               public override string Value {
+                       get { return cursorToken.Value != null ? cursorToken.Value : String.Empty; }
+               }
+
+               public WhitespaceHandling WhitespaceHandling {
                        get { return whitespaceHandling; }
                        set { whitespaceHandling = value; }
                }
 
-               public override string XmlLang
-               {
+               public override string XmlLang {
                        get { return parserContext.XmlLang; }
                }
 
-               public XmlResolver XmlResolver
-               {
+               public XmlResolver XmlResolver {
                        set { resolver = value; }
                }
 
-               public override XmlSpace XmlSpace
-               {
+               public override XmlSpace XmlSpace {
                        get { return parserContext.XmlSpace; }
                }
 
@@ -308,46 +341,39 @@ namespace System.Xml
                public override void Close ()
                {
                        readState = ReadState.Closed;
-                       foreach (XmlParserInput input in parserInputStack.ToArray ())
-                               input.Close ();
-                       this.currentInput.Close ();
+
+                       cursorToken.Clear ();
+                       currentToken.Clear ();
+                       attributeCount = 0;
+                       if (closeInput && reader != null)
+                               reader.Close ();
                }
 
                public override string GetAttribute (int i)
                {
-                       if (i > attributes.Count)
+                       if (i >= attributeCount)
                                throw new ArgumentOutOfRangeException ("i is smaller than AttributeCount");
-                       else
-                               return UnescapeAttributeValue (attributes [orderedAttributes [i]] as string);
+                       else {
+                               return attributeTokens [i].Value;
+                       }
                }
 
-               // MS.NET 1.0 documentation says that this method returns String.Empty for
-               // not-exist attribute, but in fact it returns null.
-               // That description is corrected in MS.NET 1.1 documentation.
+               // MS.NET 1.0 msdn says that this method returns String.Empty
+               // for absent attribute, but in fact it returns null.
+               // This description is corrected in MS.NET 1.1 msdn.
                public override string GetAttribute (string name)
                {
-                       return UnescapeAttributeValue (attributes [name] as string);
+                       for (int i = 0; i < attributeCount; i++)
+                               if (attributeTokens [i].Name == name)
+                                       return attributeTokens [i].Value;
+                       return null;
                }
 
                private int GetIndexOfQualifiedAttribute (string localName, string namespaceURI)
                {
-                       for(int i = 0; i < orderedAttributes.Count; i++)
-                       {
-                               string thisName = (string) orderedAttributes [i];
-
-                               int indexOfColon = thisName.IndexOf (':');
-
-                               if (indexOfColon != -1) {
-                                       string thisLocalName = thisName.Substring (indexOfColon + 1);
-
-                                       if (localName == thisLocalName) {
-                                               string thisPrefix = thisName.Substring (0, indexOfColon);
-                                               string thisNamespaceURI = LookupNamespace (thisPrefix);
-
-                                               if (namespaceURI == thisNamespaceURI)
-                                                       return i;
-                                       }
-                               } else if (localName == "xmlns" && namespaceURI == "http://www.w3.org/2000/xmlns/" && thisName == "xmlns")
+                       for (int i = 0; i < attributeCount; i++) {
+                               XmlAttributeTokenInfo ti = attributeTokens [i];
+                               if (ti.LocalName == localName && ti.NamespaceURI == namespaceURI)
                                        return i;
                        }
                        return -1;
@@ -363,94 +389,82 @@ namespace System.Xml
                        int idx = this.GetIndexOfQualifiedAttribute (localName, namespaceURI);
                        if (idx < 0)
                                return null;
-                       return UnescapeAttributeValue (attributes [orderedAttributes [idx]] as string);
+                       return attributeTokens [idx].Value;
                }
 
-               [MonoTODO]
+#if NET_2_0
+               public IDictionary GetNamespacesInScope (XmlNamespaceScope scope)
+               {
+                       return parserContext.NamespaceManager.GetNamespacesInScope (scope);
+               }
+#endif
+
                public TextReader GetRemainder ()
                {
-                       throw new NotImplementedException ();
+                       if (peekCharsIndex == peekCharsLength)
+                               return reader;
+                       return new StringReader (new string (peekChars, peekCharsIndex, peekCharsLength - peekCharsIndex) + reader.ReadToEnd ());
                }
 
+#if NET_2_0
+               public bool HasLineInfo ()
+#else
                bool IXmlLineInfo.HasLineInfo ()
+#endif
                {
                        return true;
                }
 
                public override string LookupNamespace (string prefix)
                {
-                       return parserContext.NamespaceManager.LookupNamespace (prefix);
+                       return LookupNamespace (prefix, false);
                }
 
-               public override void MoveToAttribute (int i)
+#if NET_2_0
+               public override string LookupNamespace (string prefix, bool atomizedName)
+#else
+               internal override string LookupNamespace (string prefix, bool atomizedName)
+#endif
                {
-                       MoveToElement ();
+                       return parserContext.NamespaceManager.LookupNamespace (prefix, atomizedName);
+               }
 
-                       if (attributes == null || orderedAttributes.Count < i || i < 0)
-                               throw new ArgumentOutOfRangeException ("attribute index out of range.");
+#if NET_2_0
+               string IXmlNamespaceResolver.LookupPrefix (string ns)
+               {
+                       return LookupPrefix (ns, false);
+               }
 
-                       if (orderedAttributesEnumerator == null) {
-                               SaveProperties ();
-                       }
+               public string LookupPrefix (string ns, bool atomizedName)
+               {
+                       return parserContext.NamespaceManager.LookupPrefix (ns, atomizedName);
+               }
+#endif
 
-                       orderedAttributesEnumerator = orderedAttributes.GetEnumerator ();
-                       for (int n=0; n<=i; n++)
-                               orderedAttributesEnumerator.MoveNext();
+               public override void MoveToAttribute (int i)
+               {
+                       if (i >= attributeCount)
+                               throw new ArgumentOutOfRangeException ("attribute index out of range.");
 
-                       string name = orderedAttributes [i] as string;
-                       string value = attributes [name] as string;
-                       SetProperties (
-                               XmlNodeType.Attribute, // nodeType
-                               name, // name
-                               false, // isEmptyElement
-                               value, // value
-                               false // clearAttributes
-                               );
-                       attributeValuePos = 0;
+                       currentAttribute = i;
+                       currentAttributeValue = -1;
+                       cursorToken = attributeTokens [i];
                }
 
                public override bool MoveToAttribute (string name)
                {
-                       MoveToElement ();
-                       bool match = false;
-
-                       if (attributes == null)
-                               return false;
-
-                       if (orderedAttributesEnumerator == null) {
-                               SaveProperties ();
-                       }
-
-                       orderedAttributesEnumerator = orderedAttributes.GetEnumerator ();
-                       while (orderedAttributesEnumerator.MoveNext ()) {
-                               if(name == orderedAttributesEnumerator.Current as string) {
-                                       match = true;
-                                       break;
+                       for (int i = 0; i < attributeCount; i++) {
+                               XmlAttributeTokenInfo ti = attributeTokens [i];
+                               if (ti.Name == name) {
+                                       MoveToAttribute (i);
+                                       return true;
                                }
                        }
-
-                       if (match) {
-                               string value = attributes [name] as string;
-                               SetProperties (
-                                       XmlNodeType.Attribute, // nodeType
-                                       name, // name
-                                       false, // isEmptyElement
-                                       value, // value
-                                       false // clearAttributes
-                               );
-                               attributeValuePos = 0;
-                       }
-
-                       return match;
+                       return false;
                }
 
                public override bool MoveToAttribute (string localName, string namespaceName)
                {
-                       MoveToElement ();
-
-                       if (attributes == null)
-                               return false;
-
                        int idx = GetIndexOfQualifiedAttribute (localName, namespaceName);
                        if (idx < 0)
                                return false;
@@ -460,295 +474,599 @@ namespace System.Xml
 
                public override bool MoveToElement ()
                {
-                       if (orderedAttributesEnumerator != null) {
-                               orderedAttributesEnumerator = null;
-                               if (isPropertySaved)
-                                       RestoreProperties ();
+                       if (currentToken == null)       // for attribute .ctor()
+                               return false;
+
+                       if (cursorToken == currentToken)
+                               return false;
+
+                       if (currentAttribute >= 0) {
+                               currentAttribute = -1;
+                               currentAttributeValue = -1;
+                               cursorToken = currentToken;
                                return true;
                        }
-
-                       return false;
+                       else
+                               return false;
                }
 
                public override bool MoveToFirstAttribute ()
                {
+                       if (attributeCount == 0)
+                               return false;
                        MoveToElement ();
                        return MoveToNextAttribute ();
                }
 
                public override bool MoveToNextAttribute ()
                {
-                       if (attributes == null)
+                       if (currentAttribute == 0 && attributeCount == 0)
                                return false;
-
-                       if (orderedAttributesEnumerator == null) {
-                               SaveProperties ();
-                               orderedAttributesEnumerator = orderedAttributes.GetEnumerator ();
-                       }
-
-                       if (orderedAttributesEnumerator.MoveNext ()) {
-                               string name = orderedAttributesEnumerator.Current as string;
-                               string value = attributes [name] as string;
-                               SetProperties (
-                                       XmlNodeType.Attribute, // nodeType
-                                       name, // name
-                                       false, // isEmptyElement
-                                       value, // value
-                                       false // clearAttributes
-                               );
-                               attributeValuePos = 0;
+                       if (currentAttribute + 1 < attributeCount) {
+                               currentAttribute++;
+                               currentAttributeValue = -1;
+                               cursorToken = attributeTokens [currentAttribute];
                                return true;
                        }
-
-                       return false;
+                       else
+                               return false;
                }
 
                public override bool Read ()
                {
+                       if (startNodeType == XmlNodeType.Attribute) {
+                               if (currentAttribute == 0)
+                                       return false;   // already read.
+                               ClearAttributes ();
+                               IncrementAttributeToken ();
+                               ReadAttributeValueTokens ('"');
+                               cursorToken = attributeTokens [0];
+                               currentAttributeValue = -1;
+                               readState = ReadState.Interactive;
+                               return true;
+                       }
+
                        bool more = false;
-                       isPropertySaved = false;
                        readState = ReadState.Interactive;
+                       currentLinkedNodeLineNumber = line;
+                       currentLinkedNodeLinePosition = column;
+                       useProceedingLineInfo = true;
+
+                       cursorToken = currentToken;
+                       attributeCount = 0;
+                       currentAttribute = currentAttributeValue = -1;
+                       currentToken.Clear ();
 
                        // It was moved from end of ReadStartTag ().
-                       if (depthUp)
+                       if (depthUp) {
                                ++depth;
-                       depthUp = false;
+                               depthUp = false;
+                       }
+
+                       if (shouldSkipUntilEndTag) {
+                               shouldSkipUntilEndTag = false;
+                               return ReadUntilEndTag ();
+                       }
+
+                       base64CacheStartsAt = -1;
 
                        more = ReadContent ();
 
-                       if (depth == 0 && !allowMultipleRoot && (IsEmptyElement || NodeType == XmlNodeType.EndElement))
-                               currentState = XmlNodeType.EndElement;
-                       if (maybeTextDecl != 0)
-                               maybeTextDecl--;
+                       if (!more && startNodeType == XmlNodeType.Document && currentState != XmlNodeType.EndElement)
+                               throw new XmlException ("Document element did not appear.");
 
+                       useProceedingLineInfo = false;
                        return more;
                }
 
                public override bool ReadAttributeValue ()
                {
-                       // 'attributeString' holds real string value (without their
-                       // quotation characters).
-                       //
-                       // 'attributeValuePos' holds current position
-                       // of 'attributeString' while iterating ReadAttribute().
-                       // It may be:
-                       //   -1 if ReadAttributeValue() has already finished.
-                       //    0 if ReadAttributeValue() ready to start reading.
-                       //   >0 if ReadAttributeValue() already got 1 or more values
-                       //
-                       // local 'refPosition' holds the position on the 
-                       // attributeString which may be used next time.
-
-                       if (attributeValuePos < 0)
-                               return false;
-
-                       // If not started, then initialize attributeString when parsing is at start.
-                       if (attributeValuePos == 0)
-                               attributeString =
-                                       value.Substring (1, value.Length - 2);
+                       if (readState == ReadState.Initial && startNodeType == XmlNodeType.Attribute) {
+                               Read ();
+                       }
 
-                       // It occurs when attribute dully consists of entity reference.
-                       if (attributeValuePos == attributeString.Length)
+                       if (currentAttribute < 0)
                                return false;
+                       XmlAttributeTokenInfo ti = attributeTokens [currentAttribute];
+                       if (currentAttributeValue < 0)
+                               currentAttributeValue = ti.ValueTokenStartIndex - 1;
 
-                       returnEntityReference = false;
-                       value = String.Empty;
-                       int refPosition;
-                       int loop = 0;
-
-                       do {
-                               refPosition = attributeString.IndexOf ('&', attributeValuePos);
-                               if (refPosition < 0) {
-                                       // Reached to the end of value string.
-                                       value += attributeString.Substring (attributeValuePos);
-                                       attributeValuePos = -1;
-                                       break;
-                               } else if (refPosition == attributeValuePos) {
-                                       string parsed = ReadAttributeValueReference ();
-                                       if (parsed != null)
-                                               value += parsed;
-                                       else {
-                                               // Found that an entity reference starts from this point.
-                                               // reset position to after '&'.
-                                               attributeValuePos = refPosition;
-                                               if (value.Length <= 0) {
-                                                       int endNamePos = attributeString.IndexOf (";", attributeValuePos);
-                                                       value = attributeString.Substring (attributeValuePos+1, endNamePos - attributeValuePos - 1);
-                                                       attributeValuePos += value.Length + 2;
-                                                       returnEntityReference = true;
-                                               }
-                                               break;
-                                       }
-                               } else {
-                                       value += attributeString.Substring (attributeValuePos,
-                                               refPosition - attributeValuePos);
-                                       attributeValuePos = refPosition;
-                                       continue;
-                               }
-                       } while (++loop > 0);
-
-                       if (returnEntityReference)
-                               SetProperties (XmlNodeType.EntityReference,
-                                       value,
-                                       false,
-                                       String.Empty,
-                                       false);
+                       if (currentAttributeValue < ti.ValueTokenEndIndex) {
+                               currentAttributeValue++;
+                               cursorToken = attributeValueTokens [currentAttributeValue];
+                               return true;
+                       }
                        else
-                               SetProperties (XmlNodeType.Text,
-                                       "",
-                                       false,
-                                       value,
-                                       false);
+                               return false;
+               }
 
-                       return true;
+               private int SkipIgnorableBase64Chars (char [] chars, int charsLength, int i)
+               {
+                       while (chars [i] == '=' || XmlChar.IsWhitespace (chars [i]))
+                               if (charsLength == ++i)
+                                       break;
+                       return i;
                }
 
-               [MonoTODO]
                public int ReadBase64 (byte [] buffer, int offset, int length)
                {
-                       throw new NotImplementedException ();
+                       if (offset < 0)
+                               throw new ArgumentOutOfRangeException ("offset", offset, "Offset must be non-negative integer.");
+                       else if (length < 0)
+                               throw new ArgumentOutOfRangeException ("length", length, "Length must be non-negative integer.");
+                       else if (buffer.Length < offset + length)
+                               throw new ArgumentOutOfRangeException ("buffer length is smaller than the sum of offset and length.");
+
+                       if (length == 0)        // It does not raise an error.
+                               return 0;
+
+                       int bufIndex = offset;
+                       int bufLast = offset + length;
+
+                       if (base64CacheStartsAt >= 0) {
+                               for (int i = base64CacheStartsAt; i < 3; i++) {
+                                       buffer [bufIndex++] = base64Cache [base64CacheStartsAt++];
+                                       if (bufIndex == bufLast)
+                                               return bufLast - offset;
+                               }
+                       }
+
+                       for (int i = 0; i < 3; i++)
+                               base64Cache [i] = 0;
+                       base64CacheStartsAt = -1;
+
+                       int max = (int) System.Math.Ceiling (4.0 / 3 * length);
+                       int additional = max % 4;
+                       if (additional > 0)
+                               max += 4 - additional;
+                       char [] chars = new char [max];
+                       int charsLength = ReadChars (chars, 0, max);
+
+                       byte b = 0;
+                       byte work = 0;
+                       bool loop = true;
+                       for (int i = 0; i < charsLength - 3; i++) {
+                               if ((i = SkipIgnorableBase64Chars (chars, charsLength, i)) == charsLength)
+                                       break;
+                               b = (byte) (GetBase64Byte (chars [i]) << 2);
+                               if (bufIndex < bufLast)
+                                       buffer [bufIndex] = b;
+                               else {
+                                       if (base64CacheStartsAt < 0)
+                                               base64CacheStartsAt = 0;
+                                       base64Cache [0] = b;
+                               }
+                               // charsLength mod 4 might not equals to 0.
+                               if (++i == charsLength)
+                                       break;
+                               if ((i = SkipIgnorableBase64Chars (chars, charsLength, i))  == charsLength)
+                                       break;
+                               b = GetBase64Byte (chars [i]);
+                               work = (byte) (b >> 4);
+                               if (bufIndex < bufLast) {
+                                       buffer [bufIndex] += work;
+                                       bufIndex++;
+                               }
+                               else
+                                       base64Cache [0] += work;
+
+                               work = (byte) ((b & 0xf) << 4);
+                               if (bufIndex < bufLast) {
+                                       buffer [bufIndex] = work;
+                               }
+                               else {
+                                       if (base64CacheStartsAt < 0)
+                                               base64CacheStartsAt = 1;
+                                       base64Cache [1] = work;
+                               }
+
+                               if (++i == charsLength)
+                                       break;
+                               if ((i = SkipIgnorableBase64Chars (chars, charsLength, i)) == charsLength)
+                                       break;
+                               b = GetBase64Byte (chars [i]);
+                               work = (byte) (b >> 2);
+                               if (bufIndex < bufLast) {
+                                       buffer [bufIndex] += work;
+                                       bufIndex++;
+                               }
+                               else
+                                       base64Cache [1] += work;
+
+                               work = (byte) ((b & 3) << 6);
+                               if (bufIndex < bufLast)
+                                       buffer [bufIndex] = work;
+                               else {
+                                       if (base64CacheStartsAt < 0)
+                                               base64CacheStartsAt = 2;
+                                       base64Cache [2] = work;
+                               }
+                               if (++i == charsLength)
+                                       break;
+                               if ((i = SkipIgnorableBase64Chars (chars, charsLength, i)) == charsLength)
+                                       break;
+                               work = GetBase64Byte (chars [i]);
+                               if (bufIndex < bufLast) {
+                                       buffer [bufIndex] += work;
+                                       bufIndex++;
+                               }
+                               else
+                                       base64Cache [2] += work;
+                       }
+                       return System.Math.Min (bufLast - offset, bufIndex - offset);
                }
 
-               [MonoTODO]
                public int ReadBinHex (byte [] buffer, int offset, int length)
                {
-                       throw new NotImplementedException ();
+                       if (offset < 0)
+                               throw new ArgumentOutOfRangeException ("offset", offset, "Offset must be non-negative integer.");
+                       else if (length < 0)
+                               throw new ArgumentOutOfRangeException ("length", length, "Length must be non-negative integer.");
+                       else if (buffer.Length < offset + length)
+                               throw new ArgumentOutOfRangeException ("buffer length is smaller than the sum of offset and length.");
+
+                       if (length == 0)
+                               return 0;
+
+                       char [] chars = new char [length * 2];
+                       int charsLength = ReadChars (chars, 0, length * 2);
+                       return XmlConvert.FromBinHexString (chars, offset, charsLength, buffer);
                }
 
-               [MonoTODO]
                public int ReadChars (char [] buffer, int offset, int length)
                {
-                       throw new NotImplementedException ();
+                       return ReadCharsInternal (buffer, offset, length);
                }
 
+#if NET_2_0
+               public override string ReadString ()
+               {
+                       return ReadStringInternal ();
+               }
+#elif NET_1_1
+#else
                public override string ReadInnerXml ()
                {
-                       if (readState != ReadState.Interactive)
-                               return String.Empty;
-
-                       switch (NodeType) {
-                       case XmlNodeType.Attribute:
-                               return value.Substring (1, value.Length - 2);
-                       case XmlNodeType.Element:
-                               if (IsEmptyElement)
-                                       return String.Empty;
-
-                               int startDepth = depth;
-
-                               if (innerXmlBuilder == null)
-                                       innerXmlBuilder = new StringBuilder ();
-                               innerXmlBuilder.Length = 0;
-                               bool loop = true;
-                               do {
-                                       Read ();
-                                       if (NodeType ==XmlNodeType.None)
-                                               throw new XmlException ("unexpected end of xml.");
-                                       else if (NodeType == XmlNodeType.EndElement && depth == startDepth) {
-                                               loop = false;
-                                               Read ();
-                                       }
-                                       else
-                                               innerXmlBuilder.Append (currentTag);
-                               } while (loop);
-                               string xml = innerXmlBuilder.ToString ();
-                               innerXmlBuilder.Length = 0;
-                               return xml;
-                       case XmlNodeType.None:
-                               // MS document is incorrect. Seems not to progress.
-                               return String.Empty;
-                       default:
-                               Read ();
-                               return String.Empty;
-                       }
+                       return ReadInnerXmlInternal ();
                }
 
                public override string ReadOuterXml ()
                {
-                       if (readState != ReadState.Interactive)
-                               return String.Empty;
-
-                       switch (NodeType) {
-                       case XmlNodeType.Attribute:
-                               // strictly incompatible with MS... (it holds spaces attribute between name, value and "=" char (very trivial).
-                               return String.Format ("{0}={1}{2}{1}", Name, QuoteChar, ReadInnerXml ());
-                       case XmlNodeType.Element:
-                               bool isEmpty = IsEmptyElement;
-                               string startTag = currentTag.ToString ();
-                               string name = Name;
-
-                               if (NodeType == XmlNodeType.Element && !isEmpty)
-                                       return String.Format ("{0}{1}</{2}>", startTag, ReadInnerXml (), name);
-                               else
-                                       return currentTag.ToString ();
-                       case XmlNodeType.None:
-                               // MS document is incorrect. Seems not to progress.
-                               return String.Empty;
-                       default:
-                               Read ();
-                               return String.Empty;
-                       }
+                       return ReadOuterXmlInternal ();
                }
 
                public override string ReadString ()
                {
                        return ReadStringInternal ();
                }
+#endif
 
                public void ResetState ()
                {
+                       throw new InvalidOperationException ("Cannot call ResetState when parsing an XML fragment.");
                        Init ();
                }
 
-               public override void ResolveEntity ()
+#if NET_2_0
+               [MonoTODO]
+               public override bool ReadValueAsBoolean ()
                {
-                       // XmlTextReaders don't resolve entities.
-                       throw new InvalidOperationException ("XmlTextReader cannot resolve external entities.");
+                       return base.ReadValueAsBoolean ();
                }
 
-               #endregion
-
-               #region Internals
-               // Parsed DTD Objects
-               internal DTDObjectModel DTD;
-               #endregion
+               [MonoTODO]
+               public override DateTime ReadValueAsDateTime ()
+               {
+                       return base.ReadValueAsDateTime ();
+               }
 
-               #region Privates
+               [MonoTODO]
+               public override decimal ReadValueAsDecimal ()
+               {
+                       return base.ReadValueAsDecimal ();
+               }
 
-               private XmlParserContext parserContext;
+               [MonoTODO]
+               public override double ReadValueAsDouble ()
+               {
+                       return base.ReadValueAsDouble ();
+               }
 
-               private XmlParserInput currentInput;
-               private Stack parserInputStack;
-               private ReadState readState;
+               [MonoTODO]
+               public override int ReadValueAsInt32 ()
+               {
+                       return base.ReadValueAsInt32 ();
+               }
 
-               private int depth;
-               private int elementDepth;
-               private bool depthUp;
+               [MonoTODO]
+               public override long ReadValueAsInt64 ()
+               {
+                       return base.ReadValueAsInt64 ();
+               }
 
-               private bool popScope;
-               private Stack elementStack;
-               private bool allowMultipleRoot;
+               [MonoTODO]
+               public override ICollection ReadValueAsList ()
+               {
+                       return base.ReadValueAsList ();
+               }
 
-               private XmlNodeType nodeType;
-               private string name;
-               private string prefix;
-               private string localName;
-               private string namespaceURI;
-               private bool isEmptyElement;
-               private string value;
-               private StringBuilder valueBuilder;
-               private bool valueBuilderAvailable = false;
-
-               private bool isPropertySaved;
-               private XmlNodeType saveNodeType;
-               private string saveName;
-               private string savePrefix;
-               private string saveLocalName;
-               private string saveNamespaceURI;
-               private bool saveIsEmptyElement;
-
-               private Hashtable attributes;
-               private ArrayList orderedAttributes;
-               private IEnumerator orderedAttributesEnumerator;
+               [MonoTODO]
+               public override float ReadValueAsSingle ()
+               {
+                       return base.ReadValueAsSingle ();
+               }
+
+               [MonoTODO]
+               public override string ReadValueAsString ()
+               {
+                       return ReadString ();
+               }
+
+               [MonoTODO]
+               public override object ReadValueAs (Type type)
+               {
+                       return base.ReadValueAs (type);
+               }
+
+               [MonoTODO]
+               public override object ReadValueAs (Type type, IXmlNamespaceResolver resolver)
+               {
+                       return base.ReadValueAs (type, resolver);
+               }
+#endif
+
+               public override void ResolveEntity ()
+               {
+                       // XmlTextReader does not resolve entities.
+                       throw new InvalidOperationException ("XmlTextReader cannot resolve external entities.");
+               }
+
+#if NET_2_0
+               [MonoTODO ("Implement for performance reason")]
+               public override void Skip ()
+               {
+                       base.Skip ();
+               }
+#endif
+               #endregion
+
+               #region Internals
+               // Parsed DTD Objects
+#if DTD_HANDLE_EVENTS
+               internal event ValidationEventHandler ValidationEventHandler;
+#endif
+
+               internal DTDObjectModel DTD {
+                       get { return parserContext.Dtd; }
+               }
+
+               internal XmlResolver Resolver {
+                       get { return resolver; }
+               }
+               #endregion
+
+               #region Privates
+               internal class XmlTokenInfo
+               {
+                       public XmlTokenInfo (XmlTextReader xtr, bool isPrimaryToken)
+                       {
+                               this.isPrimaryToken = isPrimaryToken;
+                               Reader = xtr;
+                               Clear ();
+                       }
+
+                       bool isPrimaryToken;
+                       string valueCache;
+
+                       protected XmlTextReader Reader;
+
+                       public string Name;
+                       public string LocalName;
+                       public string Prefix;
+                       public string NamespaceURI;
+                       public bool IsEmptyElement;
+                       public char QuoteChar;
+                       public int LineNumber;
+                       public int LinePosition;
+
+                       public XmlNodeType NodeType;
+
+                       public virtual string Value {
+                               get {
+                                       if (valueCache != null)
+                                               return valueCache;
+                                       switch (NodeType) {
+                                       case XmlNodeType.Text:
+                                       case XmlNodeType.SignificantWhitespace:
+                                       case XmlNodeType.Whitespace:
+                                       case XmlNodeType.Comment:
+                                       case XmlNodeType.CDATA:
+                                       case XmlNodeType.ProcessingInstruction:
+                                               valueCache = Reader.CreateValueString ();
+                                               return valueCache;
+                                       }
+                                       return null;
+                               }
+                               set { valueCache = value; }
+                       }
+
+                       public virtual void Clear ()
+                       {
+                               valueCache = null;
+                               NodeType = XmlNodeType.None;
+                               Name = LocalName = Prefix = NamespaceURI = String.Empty;
+                               IsEmptyElement = false;
+                               QuoteChar = '"';
+                               LineNumber = LinePosition = 0;
+                       }
+
+                       internal virtual void FillNames ()
+                       {
+                               if (Reader.Namespaces) {
+                                       int indexOfColon = -1;
+                                       switch (NodeType) {
+                                       case XmlNodeType.Attribute:
+                                       case XmlNodeType.Element:
+                                       case XmlNodeType.EndElement:
+                                               indexOfColon = Name.IndexOf (':');
+                                               break;
+                                       }
+
+                                       if (indexOfColon == -1) {
+                                               Prefix = String.Empty;
+                                               LocalName = Name;
+                                       } else {
+                                               // This improves speed by at least nearly 5%, but eats more memory at least nearly 0.3%
+                                               // However, this might be reverted if NameTable is got improved.
+                                               char [] nameArr = Name.ToCharArray ();
+                                               Prefix = Reader.NameTable.Add (nameArr, 0, indexOfColon);
+                                               LocalName = Reader.NameTable.Add (nameArr, indexOfColon + 1, nameArr.Length - indexOfColon - 1);
+//                                             Prefix = Reader.NameTable.Add (Name.Substring (0, indexOfColon));
+//                                             LocalName = Reader.NameTable.Add (Name.Substring (indexOfColon + 1));
+                                       }
+
+                                       // NamespaceURI
+                                       switch (NodeType) {
+                                       case XmlNodeType.Attribute:
+                                               if (Prefix.Length == 0)
+                                                       NamespaceURI = string.Empty;
+                                               else
+                                                       NamespaceURI = Reader.LookupNamespace (Prefix, true);
+                                               break;
+
+                                       case XmlNodeType.Element:
+                                       case XmlNodeType.EndElement:
+                                               NamespaceURI = Reader.LookupNamespace (Prefix, true);
+                                               break;
+                                       default:
+                                               NamespaceURI = "";
+                                               break;
+                                       }
+                               } else {
+                                       Prefix = String.Empty;
+                                       LocalName = Name;
+                               }
+                       }
+               }
+
+               internal class XmlAttributeTokenInfo : XmlTokenInfo
+               {
+                       public XmlAttributeTokenInfo (XmlTextReader reader)
+                               : base (reader, false)
+                       {
+                               NodeType = XmlNodeType.Attribute;
+                       }
+
+                       public int ValueTokenStartIndex;
+                       public int ValueTokenEndIndex;
+                       string valueCache;
+                       bool cachedNormalization;
+                       StringBuilder tmpBuilder = new StringBuilder ();
+
+                       public override string Value {
+                               get {
+                                       if (cachedNormalization != Reader.Normalization)
+                                               valueCache = null;
+                                       if (valueCache != null)
+                                               return valueCache;
+
+                                       cachedNormalization = Reader.Normalization;
+
+                                       // An empty value should return String.Empty.
+                                       if (ValueTokenStartIndex == ValueTokenEndIndex) {
+                                               XmlTokenInfo ti = Reader.attributeValueTokens [ValueTokenStartIndex];
+                                               if (ti.NodeType == XmlNodeType.EntityReference)
+                                                       valueCache = String.Concat ("&", ti.Name, ";");
+                                               else
+                                                       valueCache = ti.Value;
+                                               if (cachedNormalization)
+                                                       NormalizeSpaces ();
+                                               return valueCache;
+                                       }
+
+                                       tmpBuilder.Length = 0;
+                                       for (int i = ValueTokenStartIndex; i <= ValueTokenEndIndex; i++) {
+                                               XmlTokenInfo ti = Reader.attributeValueTokens [i];
+                                               if (ti.NodeType == XmlNodeType.Text)
+                                                       tmpBuilder.Append (ti.Value);
+                                               else {
+                                                       tmpBuilder.Append ('&');
+                                                       tmpBuilder.Append (ti.Name);
+                                                       tmpBuilder.Append (';');
+                                               }
+                                       }
+
+                                       valueCache = tmpBuilder.ToString ();
+                                       if (cachedNormalization)
+                                               NormalizeSpaces ();
+                                       return valueCache;
+                               }
+
+                               set { valueCache = value; }
+                       }
+
+                       public override void Clear ()
+                       {
+                               base.Clear ();
+                               valueCache = null;
+                               NodeType = XmlNodeType.Attribute;
+                               ValueTokenStartIndex = ValueTokenEndIndex = 0;
+                       }
+
+                       internal override void FillNames ()
+                       {
+                               base.FillNames ();
+                               if (Prefix == "xmlns" || Name == "xmlns")
+                                       NamespaceURI = XmlNamespaceManager.XmlnsXmlns;
+                       }
+
+                       private void NormalizeSpaces ()
+                       {
+                               tmpBuilder.Length = 0;
+                               for (int i = 0; i < valueCache.Length; i++)
+                                       switch (valueCache [i]) {
+                                       case '\r':
+                                               if (i + 1 < valueCache.Length && valueCache [i + 1] == '\n')
+                                                       i++;
+                                               goto case '\n';
+                                       case '\t':
+                                       case '\n':
+                                               tmpBuilder.Append (' ');
+                                               break;
+                                       default:
+                                               tmpBuilder.Append (valueCache [i]);
+                                               break;
+                                       }
+                               valueCache = tmpBuilder.ToString ();
+                       }
+               }
+
+               private XmlTokenInfo cursorToken;
+               private XmlTokenInfo currentToken;
+               private XmlAttributeTokenInfo currentAttributeToken;
+               private XmlTokenInfo currentAttributeValueToken;
+               private XmlAttributeTokenInfo [] attributeTokens = new XmlAttributeTokenInfo [10];
+               private XmlTokenInfo [] attributeValueTokens = new XmlTokenInfo [10];
+               private int currentAttribute;
+               private int currentAttributeValue;
+               private int attributeCount;
+
+               private XmlParserContext parserContext;
+
+               private ReadState readState;
+
+               private int depth;
+               private int elementDepth;
+               private bool depthUp;
+
+               private bool popScope;
+
+               private string [] elementNames;
+               int elementNameStackPos;
+
+               private bool allowMultipleRoot;
+
+               private bool isStandalone;
 
                private bool returnEntityReference;
                private string entityReferenceName;
@@ -756,80 +1074,120 @@ namespace System.Xml
                private char [] nameBuffer;
                private int nameLength;
                private int nameCapacity;
-               private const int initialNameCapacity = 256;
+               private const int initialNameCapacity = 32;
 
-               private StringBuilder valueBuffer;
+               private char [] valueBuffer;
+               private int valueLength;
+               private int valueCapacity;
+               private const int initialValueCapacity = 256;
 
-               // A buffer for ReadContent for ReadOuterXml
-               private StringBuilder currentTag {
-                       get {
-                               return currentInput.CurrentMarkup;
-                       }
-               }
+               private char [] currentTagBuffer;
+               private int currentTagLength;
+               private int currentTagCapacity;
+               private const int initialCurrentTagCapacity = 256;
 
-               private string attributeString;
-               private int attributeValuePos;
-               // This should be only referenced(used) by ReadInnerXml(). Kind of flyweight pattern.
-               private StringBuilder innerXmlBuilder;
+               private TextReader reader;
+               private char [] peekChars;
+               private int peekCharsIndex;
+               private int peekCharsLength;
+               private const int peekCharCapacity = 1024;
 
-               // Parameter entity placeholder
-               private Hashtable parameterEntities;
-               private int dtdIncludeSect;
-               private bool isIntSubset;
+               private int line;
+               private int column;
 
+               private int currentLinkedNodeLineNumber;
+               private int currentLinkedNodeLinePosition;
+               private bool useProceedingLineInfo;
+
+               private XmlNodeType startNodeType;
                // State machine attribute.
                //      XmlDeclaration: after the first node.
                //      DocumentType: after doctypedecl
                //      Element: inside document element
                //      EndElement: after document element
                private XmlNodeType currentState;
-               private int maybeTextDecl;
+
+               // For ReadChars()/ReadBase64()/ReadBinHex()
+               private bool shouldSkipUntilEndTag;
+               private byte [] base64Cache = new byte [3];
+               private int base64CacheStartsAt;
 
                // These values are never re-initialized.
-               private XmlResolver resolver = new XmlUrlResolver ();
                private bool namespaces = true;
                private WhitespaceHandling whitespaceHandling = WhitespaceHandling.All;
+               private XmlResolver resolver = new XmlUrlResolver ();
                private bool normalization = false;
 
+               private bool checkCharacters;
+               private bool prohibitDtd = false;
+               private bool closeInput = true;
+               private EntityHandling entityHandling; // 2.0
+
                private void Init ()
                {
+                       currentToken = new XmlTokenInfo (this, true);
+                       cursorToken = currentToken;
+                       currentAttribute = -1;
+                       currentAttributeValue = -1;
+                       attributeCount = 0;
+
                        readState = ReadState.Initial;
-                       currentState = XmlNodeType.None;
-                       maybeTextDecl = 0;
                        allowMultipleRoot = false;
 
                        depth = 0;
+                       elementDepth = 0;
                        depthUp = false;
 
-                       popScope = false;
-                       parserInputStack = new Stack ();
-                       elementStack = new Stack();
-
-                       nodeType = XmlNodeType.None;
-                       name = String.Empty;
-                       prefix = String.Empty;
-                       localName = string.Empty;
-                       isEmptyElement = false;
-                       value = String.Empty;
-
-                       attributes = new Hashtable ();
-                       attributeString = String.Empty;
-                       orderedAttributes = new ArrayList ();
-                       orderedAttributesEnumerator = null;
+                       popScope = allowMultipleRoot = false;
+                       elementNames = new string [10];
+                       elementNameStackPos = 0;
 
+                       isStandalone = false;
                        returnEntityReference = false;
                        entityReferenceName = String.Empty;
 
                        nameBuffer = new char [initialNameCapacity];
                        nameLength = 0;
                        nameCapacity = initialNameCapacity;
-                       
-                       valueBuffer = new StringBuilder (8192);
-                       parameterEntities = new Hashtable ();
+
+                       valueBuffer = new char [initialValueCapacity];
+                       valueLength = 0;
+                       valueCapacity = initialValueCapacity;
+
+                       currentTagBuffer = new char [initialCurrentTagCapacity];
+                       currentTagLength = 0;
+                       currentTagCapacity = initialCurrentTagCapacity;
+
+                       peekCharsIndex = 0;
+                       peekCharsLength = 0;
+                       if (peekChars == null)
+                               peekChars = new char [peekCharCapacity];
+
+                       line = 1;
+                       column = 1;
+                       currentTagLength = 0;
+
+                       currentLinkedNodeLineNumber = currentLinkedNodeLinePosition = 0;
+                       useProceedingLineInfo = false;
+
+                       currentState = XmlNodeType.None;
+
+                       shouldSkipUntilEndTag = false;
+                       base64CacheStartsAt = -1;
+
+                       checkCharacters = true;
+#if NET_2_0
+                       if (Settings != null)
+                               checkCharacters = Settings.CheckCharacters;
+#endif
+                       prohibitDtd = false;
+                       closeInput = true;
+                       entityHandling = EntityHandling.ExpandCharEntities;
                }
 
                private void InitializeContext (string url, XmlParserContext context, TextReader fragment, XmlNodeType fragType)
                {
+                       startNodeType = fragType;
                        parserContext = context;
                        if (context == null) {
                                XmlNameTable nt = new NameTable ();
@@ -839,17 +1197,24 @@ namespace System.Xml
                                        XmlSpace.None);
                        }
 
-                       if (url != null && url != String.Empty) {
-                               string path = Path.GetFullPath ("./a");
-                               Uri uri = new Uri (new Uri (path), url);
+                       if (url != null && url.Length > 0) {
+                               Uri uri = null;
+                               try {
+                                       uri = new Uri (url);
+                               } catch (Exception) {
+                                       string path = Path.GetFullPath ("./a");
+                                       uri = new Uri (new Uri (path), url);
+                               }
                                parserContext.BaseURI = uri.ToString ();
                        }
 
                        Init ();
 
+                       reader = fragment;
+
                        switch (fragType) {
                        case XmlNodeType.Attribute:
-                               value = String.Format ("{0}{1}{0}", "'", fragment.ReadToEnd ().Replace ("'", "&apos;"));
+                               reader = new StringReader (fragment.ReadToEnd ().Replace ("\"", "&quot;"));
                                break;
                        case XmlNodeType.Element:
                                currentState = XmlNodeType.Element;
@@ -860,10 +1225,30 @@ namespace System.Xml
                        default:
                                throw new XmlException (String.Format ("NodeType {0} is not allowed to create XmlTextReader.", fragType));
                        }
+               }
+
+#if NET_2_0
+               [MonoTODO ("Test")]
+               internal ConformanceLevel Conformance {
+                       set {
+                               if (value == ConformanceLevel.Fragment) {
+                                       currentState = XmlNodeType.Element;
+                                       allowMultipleRoot = true;
+                               }
+                       }
+               }
+
+               internal void AdjustLineInfoOffset (int lineNumberOffset, int linePositionOffset)
+               {
+                       line += lineNumberOffset;
+                       column += linePositionOffset;
+               }
 
-                       this.currentInput = new XmlParserInput (fragment, url);
-                       StreamReader sr = fragment as StreamReader;
+               internal void SetNameTable (XmlNameTable nameTable)
+               {
+                       parserContext.NameTable = nameTable;
                }
+#endif
 
                // Use this method rather than setting the properties
                // directly so that all the necessary properties can
@@ -877,115 +1262,96 @@ namespace System.Xml
                        string value,
                        bool clearAttributes)
                {
-                       this.nodeType = nodeType;
-                       this.name = name;
-                       this.isEmptyElement = isEmptyElement;
-                       this.value = value;
-                       this.elementDepth = depth;
-                       this.valueBuilderAvailable = false;
-
-                       if (clearAttributes)
-                               ClearAttributes ();
-
-                       if (namespaces) {
-                               int indexOfColon = name.IndexOf (':');
-
-                               if (indexOfColon == -1) {
-                                       prefix = String.Empty;
-                                       localName = name;
-                               } else {
-                                       prefix = name.Substring (0, indexOfColon);
-                                       localName = name.Substring (indexOfColon + 1);
-                               }
-                       } else {
-                               prefix = String.Empty;
-                               localName = name;
-                       }
-
-                       switch (nodeType) {
-                       case XmlNodeType.Attribute:
-                               if (prefix == string.Empty) namespaceURI = string.Empty;
-                               else namespaceURI = LookupNamespace (prefix);
-                               if (localName == "xmlns" && prefix == "")
-                                       namespaceURI = "http://www.w3.org/2000/xmlns/";
-                               break;
-
-                       case XmlNodeType.Element:
-                       case XmlNodeType.EndElement:
-                               namespaceURI = LookupNamespace (prefix);
-                               break;
-                       default:
-                               namespaceURI = "";
-                               break;
-                       }
+                       SetProperties (currentToken, nodeType, name, isEmptyElement, value, clearAttributes);
+                       currentToken.LineNumber = this.currentLinkedNodeLineNumber;
+                       currentToken.LinePosition = this.currentLinkedNodeLinePosition;
                }
-               
+
                private void SetProperties (
+                       XmlTokenInfo token,
                        XmlNodeType nodeType,
                        string name,
                        bool isEmptyElement,
-                       StringBuilder value,
-                       bool clearAttributes) {
-                       SetProperties (nodeType, name, isEmptyElement, (string)null, clearAttributes);
-                       this.valueBuilderAvailable = true;
-                       this.valueBuilder = value;
-               }
-
-               private void SaveProperties ()
+                       string value,
+                       bool clearAttributes)
                {
-                       // If already saved, then return.
-                       if (isPropertySaved)
-                               return;
+                       token.Clear ();
+                       token.NodeType = nodeType;
+                       token.Name = name;
+                       token.IsEmptyElement = isEmptyElement;
+                       token.Value = value;
+                       this.elementDepth = depth;
+
+                       if (clearAttributes)
+                               ClearAttributes ();
 
-                       saveNodeType = nodeType;
-                       saveName = name;
-                       savePrefix = prefix;
-                       saveLocalName = localName;
-                       saveNamespaceURI = namespaceURI;
-                       saveIsEmptyElement = isEmptyElement;
-                       // An element's value is always String.Empty.
-                       isPropertySaved = true;
+                       token.FillNames ();
                }
 
-               private void RestoreProperties ()
+               private void ClearAttributes ()
                {
-                       nodeType = saveNodeType;
-                       name = saveName;
-                       prefix = savePrefix;
-                       localName = saveLocalName;
-                       namespaceURI = saveNamespaceURI;
-                       isEmptyElement = saveIsEmptyElement;
-                       value = String.Empty;
-                       isPropertySaved = false;
+                       for (int i = 0; i < attributeCount; i++)
+                               attributeTokens [i].Clear ();
+                       attributeCount = 0;
+                       currentAttribute = -1;
+                       currentAttributeValue = -1;
                }
 
-               private void AddAttribute (string name, string value)
+               private int PeekChar ()
                {
-                       if (attributes.ContainsKey (name))
-                               throw new XmlException (this as IXmlLineInfo,
-                                       String.Format ("Attribute {0} already exists.", name));
-                       attributes.Add (name, value);
-                       orderedAttributes.Add (name);
+                       if (peekCharsLength == peekCharsIndex) {
+                               if (!ReadTextReader ())
+                                       return -1;
+                               return PeekChar ();
+                       }
+                       else {
+                               char c = peekChars [peekCharsIndex];
+                               if (c != 0) return c;
+                               else return -1;
+                       }
                }
 
-               private void ClearAttributes ()
+               private int ReadChar ()
                {
-                       if (attributes.Count > 0) {
-                               attributes.Clear ();
-                               orderedAttributes.Clear ();
+                       int ch;
+
+                       if (peekCharsLength == peekCharsIndex) {
+                               if (!ReadTextReader ())
+                                       return -1;
+                               return ReadChar ();
                        }
+                       ch = peekChars [peekCharsIndex++];
 
-                       orderedAttributesEnumerator = null;
+                       if (ch == '\n') {
+                               line++;
+                               column = 1;
+                       } else if (ch == 0) {
+                               return -1;
+                       } else {
+                               column++;
+                       }
+                       if (currentState != XmlNodeType.Element)
+                               AppendCurrentTagChar (ch);
+                       return ch;
                }
 
-               private int PeekChar ()
+               private bool ReadTextReader ()
                {
-                       return currentInput.PeekChar ();
+                       peekCharsIndex = 0;
+                       peekCharsLength = reader.Read (peekChars, 0, peekCharCapacity);
+                       if (peekCharsLength == 0)
+                               return false;
+                       return true;
                }
 
-               private int ReadChar ()
+               private string ExpandSurrogateChar (int ch)
                {
-                       return currentInput.ReadChar ();
+                       if (ch < Char.MaxValue)
+                               return ((char) ch).ToString ();
+                       else {
+                               char [] tmp = new char [] {(char) (ch / 0x10000 + 0xD800 - 1), (char) (ch % 0x10000 + 0xDC00)};
+                               return new string (tmp);
+                       }
                }
 
                // This should really keep track of some state so
@@ -993,45 +1359,52 @@ namespace System.Xml
                // element or text outside of the document element.
                private bool ReadContent ()
                {
-                       currentTag.Length = 0;
+                       currentTagLength = 0;
                        if (popScope) {
                                parserContext.NamespaceManager.PopScope ();
                                popScope = false;
                        }
 
-                       if (returnEntityReference) {
+                       if (returnEntityReference)
                                SetEntityReferenceProperties ();
-                       } else {
-                               switch (PeekChar ()) {
-                               case '<':
-                                       ReadChar ();
-                                       ReadTag ();
-                                       break;
-                               case '\r': goto case ' ';
-                               case '\n': goto case ' ';
-                               case '\t': goto case ' ';
-                               case ' ':
-                                       if (whitespaceHandling == WhitespaceHandling.All ||
-                                               whitespaceHandling == WhitespaceHandling.Significant)
-                                               return ReadWhitespace ();
-
-                                       SkipWhitespace ();
-                                       return ReadContent ();
-                               case -1:
-                                       if (depth > 0)
-                                               throw new XmlException ("unexpected end of file. Current depth is " + depth);
+                       else {
+                               int c = PeekChar ();
+                               if (c == -1) {
                                        readState = ReadState.EndOfFile;
+                                       ClearValueBuffer ();
                                        SetProperties (
                                                XmlNodeType.None, // nodeType
                                                String.Empty, // name
                                                false, // isEmptyElement
-                                               String.Empty, // value
+                                               null, // value
                                                true // clearAttributes
                                        );
-                                       break;
-                               default:
-                                       ReadText (true);
-                                       break;
+                                       if (depth > 0)
+                                               throw new XmlException ("unexpected end of file. Current depth is " + depth);
+
+                                       return false;
+                               } else {
+                                       switch ((char) c) {
+                                       case '<':
+                                               ReadChar ();
+                                               ReadTag ();
+                                               break;
+                                       case '\r': goto case ' ';
+                                       case '\n': goto case ' ';
+                                       case '\t': goto case ' ';
+                                       case ' ':
+                                               if (whitespaceHandling == WhitespaceHandling.All ||
+                                                       whitespaceHandling == WhitespaceHandling.Significant)
+                                                       ReadWhitespace ();
+                                               else {
+                                                       SkipWhitespace ();
+                                                       return ReadContent ();
+                                               }
+                                               break;
+                                       default:
+                                               ReadText (true);
+                                               break;
+                                       }
                                }
                        }
                        return this.ReadState != ReadState.EndOfFile;
@@ -1039,11 +1412,21 @@ namespace System.Xml
 
                private void SetEntityReferenceProperties ()
                {
+                       DTDEntityDeclaration decl = DTD != null ? DTD.EntityDecls [entityReferenceName] : null;
+                       if (this.isStandalone)
+                               if (DTD == null || decl == null || !decl.IsInternalSubset)
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Standalone document must not contain any references to an non-internally declared entity.");
+                       if (decl != null && decl.NotationName != null)
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "Reference to any unparsed entities is not allowed here.");
+
+                       ClearValueBuffer ();
                        SetProperties (
                                XmlNodeType.EntityReference, // nodeType
                                entityReferenceName, // name
                                false, // isEmptyElement
-                               String.Empty, // value
+                               null, // value
                                true // clearAttributes
                        );
 
@@ -1079,11 +1462,14 @@ namespace System.Xml
                {
                        if (currentState == XmlNodeType.EndElement)
                                throw new XmlException (this as IXmlLineInfo,
-                                       "Element cannot appear in this state.");
+                                       "Multiple document element was detected.");
                        currentState = XmlNodeType.Element;
 
                        parserContext.NamespaceManager.PushScope ();
 
+                       currentLinkedNodeLineNumber = line;
+                       currentLinkedNodeLinePosition = column;
+
                        string name = ReadName ();
                        if (currentState == XmlNodeType.EndElement)
                                throw new XmlException (this as IXmlLineInfo,"document has terminated, cannot open new element");
@@ -1093,12 +1479,31 @@ namespace System.Xml
                        ClearAttributes ();
 
                        SkipWhitespace ();
-                       if (XmlConstructs.IsNameStart (PeekChar ()))
+                       if (XmlChar.IsFirstNameChar (PeekChar ()))
                                ReadAttributes (false);
+                       cursorToken = this.currentToken;
+
+                       // fill namespaces
+                       for (int i = 0; i < attributeCount; i++)
+                               attributeTokens [i].FillNames ();
+
+                       // quick name check
+                       for (int i = 0; i < attributeCount; i++) {
+                               for (int j = i + 1; j < attributeCount; j++)
+                                       if (Object.ReferenceEquals (attributeTokens [i].Name, attributeTokens [j].Name) ||
+                                               (Object.ReferenceEquals (attributeTokens [i].LocalName, attributeTokens [j].LocalName) &&
+                                               Object.ReferenceEquals (attributeTokens [i].NamespaceURI, attributeTokens [j].NamespaceURI)))
+                                               throw new XmlException (this as IXmlLineInfo,
+                                                       "Attribute name and qualified name must be identical.");
+                       }
 
                        string baseUri = GetAttribute ("xml:base");
-                       if (baseUri != null)
-                               parserContext.BaseURI = baseUri;
+                       if (baseUri != null) {
+                               if (this.resolver != null)
+                                       parserContext.BaseURI = resolver.ResolveUri (new Uri (BaseURI), baseUri).ToString ();
+                               else
+                                       parserContext.BaseURI = baseUri;
+                       }
                        string xmlLang = GetAttribute ("xml:lang");
                        if (xmlLang != null)
                                parserContext.XmlLang = xmlLang;
@@ -1118,19 +1523,43 @@ namespace System.Xml
                        }
                        else {
                                depthUp = true;
-                               elementStack.Push (name);
+                               PushElementName (name);
                                parserContext.PushScope ();
                        }
 
                        Expect ('>');
-
                        SetProperties (
                                XmlNodeType.Element, // nodeType
                                name, // name
                                isEmptyElement, // isEmptyElement
-                               String.Empty, // value
+                               null, // value
                                false // clearAttributes
                        );
+
+                       if (LookupNamespace (Prefix) == null)
+                               throw new XmlException (String.Format ("'{0}' is undeclared namespace.", Prefix));
+                       try {
+                               for (int i = 0; i < attributeCount; i++) {
+                                       MoveToAttribute (i);
+                                       if (LookupNamespace (Prefix) == null)
+                                               throw new XmlException (String.Format ("'{0}' is undeclared namespace.", Prefix));
+                               }
+                       } finally {
+                               MoveToElement ();
+                       }
+
+                       if (IsEmptyElement)
+                               CheckCurrentStateUpdate ();
+               }
+
+               private void PushElementName (string name)
+               {
+                       if (elementNames.Length == elementNameStackPos) {
+                               string [] newArray = new string [elementNames.Length * 2];
+                               Array.Copy (elementNames, 0, newArray, 0, elementNameStackPos);
+                               elementNames = newArray;
+                       }
+                       elementNames [elementNameStackPos++] = name;
                }
 
                // The reader is positioned on the first character
@@ -1141,16 +1570,18 @@ namespace System.Xml
                                throw new XmlException (this as IXmlLineInfo,
                                        "End tag cannot appear in this state.");
 
+                       currentLinkedNodeLineNumber = line;
+                       currentLinkedNodeLinePosition = column;
+
                        string name = ReadName ();
-                       if (elementStack.Count == 0)
+                       if (elementNameStackPos == 0)
                                throw new XmlException (this as IXmlLineInfo,"closing element without matching opening element");
-                       string expected = (string)elementStack.Pop();
+                       string expected = elementNames [--elementNameStackPos];
                        if (expected != name)
                                throw new XmlException (this as IXmlLineInfo,String.Format ("unmatched closing element: expected {0} but found {1}", expected, name));
                        parserContext.PopScope ();
 
-                       SkipWhitespace ();
-                       Expect ('>');
+                       ExpectAfterWhitespace ('>');
 
                        --depth;
 
@@ -1158,29 +1589,43 @@ namespace System.Xml
                                XmlNodeType.EndElement, // nodeType
                                name, // name
                                false, // isEmptyElement
-                               String.Empty, // value
+                               null, // value
                                true // clearAttributes
                        );
 
                        popScope = true;
+
+                       CheckCurrentStateUpdate ();
                }
 
-               private void AppendNameChar (int ch)
+               private void CheckCurrentStateUpdate ()
                {
-                       CheckNameCapacity ();
-                       nameBuffer [nameLength++] = (char)ch;
+                       if (depth == 0 && !allowMultipleRoot && (IsEmptyElement || NodeType == XmlNodeType.EndElement))
+                               currentState = XmlNodeType.EndElement;
                }
 
-               private void CheckNameCapacity ()
+               private void AppendNameChar (int ch)
                {
-                       if (nameLength == nameCapacity) {
-                               nameCapacity = nameCapacity * 2;
-                               char [] oldNameBuffer = nameBuffer;
-                               nameBuffer = new char [nameCapacity];
-                               Array.Copy (oldNameBuffer, nameBuffer, nameLength);
+                       if (nameLength == nameCapacity)
+                               ExpandNameCapacity ();
+                       if (ch < Char.MaxValue)
+                               nameBuffer [nameLength++] = (char) ch;
+                       else {
+                               nameBuffer [nameLength++] = (char) (ch / 0x10000 + 0xD800 - 1);
+                               if (nameLength == nameCapacity)
+                                       ExpandNameCapacity ();
+                               nameBuffer [nameLength++] = (char) (ch % 0x10000 + 0xDC00);
                        }
                }
 
+               private void ExpandNameCapacity ()
+               {
+                       nameCapacity = nameCapacity * 2;
+                       char [] oldNameBuffer = nameBuffer;
+                       nameBuffer = new char [nameCapacity];
+                       Array.Copy (oldNameBuffer, nameBuffer, nameLength);
+               }
+
                private string CreateNameString ()
                {
                        return parserContext.NameTable.Add (nameBuffer, 0, nameLength);
@@ -1188,51 +1633,127 @@ namespace System.Xml
 
                private void AppendValueChar (int ch)
                {
-                       valueBuffer.Append ((char)ch);
+                       if (valueLength == valueCapacity)
+                               ExpandValueCapacity ();
+                       if (ch < Char.MaxValue)
+                               valueBuffer [valueLength++] = (char) ch;
+                       else {
+                               valueBuffer [valueLength++] = (char) (ch / 0x10000 + 0xD800 - 1);
+                               if (valueLength == valueCapacity)
+                                       ExpandValueCapacity ();
+                               valueBuffer [valueLength++] = (char) (ch % 0x10000 + 0xDC00);
+                       }
+               }
+
+               private void ExpandValueCapacity ()
+               {
+                       valueCapacity = valueCapacity * 2;
+                       char [] oldValueBuffer = valueBuffer;
+                       valueBuffer = new char [valueCapacity];
+                       Array.Copy (oldValueBuffer, valueBuffer, valueLength);
                }
 
                private string CreateValueString ()
                {
-                       return valueBuffer.ToString ();
+                       return new string (valueBuffer, 0, valueLength);
                }
-               
+
                private void ClearValueBuffer ()
                {
-                       valueBuffer.Length = 0;
+                       valueLength = 0;
                }
 
-               // The reader is positioned on the first character
-               // of the text.
-               private void ReadText (bool cleanValue)
+               private void AppendCurrentTagChar (int ch)
                {
-                       if (currentState != XmlNodeType.Element)
-                               throw new XmlException (this as IXmlLineInfo,
-                                       "Text node cannot appear in this state.");
+                       if (currentTagLength == currentTagCapacity)
+                               ExpandCurrentTagCapacity ();
+                       if (ch < Char.MaxValue)
+                               currentTagBuffer [currentTagLength++] = (char) ch;
+                       else {
+                               currentTagBuffer [currentTagLength++] = (char) (ch / 0x10000 + 0xD800 - 1);
+                               if (currentTagLength == currentTagCapacity)
+                                       ExpandCurrentTagCapacity ();
+                               currentTagBuffer [currentTagLength++] = (char) (ch % 0x10000 + 0xDC00);
+                       }
+               }
+
+               private void ExpandCurrentTagCapacity ()
+               {
+                       currentTagCapacity = currentTagCapacity * 2;
+                       char [] oldCurrentTagBuffer = currentTagBuffer;
+                       currentTagBuffer = new char [currentTagCapacity];
+                       Array.Copy (oldCurrentTagBuffer, currentTagBuffer, currentTagLength);
+               }
+
+               private string CreateCurrentTagString ()
+               {
+                       return new string (currentTagBuffer, 0, currentTagLength);
+               }
+
+               private void ClearCurrentTagBuffer ()
+               {
+                       currentTagLength = 0;
+               }
+
+               // The reader is positioned on the first character
+               // of the text.
+               private void ReadText (bool notWhitespace)
+               {
+                       if (currentState != XmlNodeType.Element)
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "Text node cannot appear in this state.");
 
-                       if (cleanValue)
+                       if (notWhitespace)
                                ClearValueBuffer ();
 
                        int ch = PeekChar ();
+                       bool previousWasCloseBracket = false;
 
                        while (ch != '<' && ch != -1) {
                                if (ch == '&') {
                                        ReadChar ();
-                                       if (ReadReference (false))
+                                       ch = ReadReference (false);
+                                       if (returnEntityReference) // Returns -1 if char validation should not be done
                                                break;
-                               } else
-                                       AppendValueChar (ReadChar ());
+                               } else if (normalization && ch == '\r') {
+                                       ReadChar ();
+                                       ch = ReadChar ();
+                                       if (ch != '\n')
+                                               // append '\n' instead of '\r'.
+                                               AppendValueChar ('\n');
+                                       // and in case of "\r\n", discard '\r'.
+                               } else {
+                                       if (CharacterChecking && XmlChar.IsInvalid (ch))
+                                               throw new XmlException (this, "Not allowed character was found.");
+                                       ch = ReadChar ();
+                               }
 
+                               AppendValueChar (ch);
+
+                               // Block "]]>"
+                               if (ch == ']') {
+                                       if (previousWasCloseBracket)
+                                               if (PeekChar () == '>')
+                                                       throw new XmlException (this as IXmlLineInfo,
+                                                               "Inside text content, character sequence ']]>' is not allowed.");
+                                       previousWasCloseBracket = true;
+                               }
+                               else if (previousWasCloseBracket)
+                                       previousWasCloseBracket = false;
                                ch = PeekChar ();
+                               notWhitespace = true;
                        }
 
-                       if (returnEntityReference && valueBuffer.Length == 0) {
+                       if (returnEntityReference && valueLength == 0) {
                                SetEntityReferenceProperties ();
                        } else {
+                               XmlNodeType nodeType = notWhitespace ? XmlNodeType.Text :
+                                       this.XmlSpace == XmlSpace.Preserve ? XmlNodeType.SignificantWhitespace : XmlNodeType.Whitespace;
                                SetProperties (
-                                       XmlNodeType.Text, // nodeType
+                                       nodeType, // nodeType
                                        String.Empty, // name
                                        false, // isEmptyElement
-                                       valueBuffer, // value
+                                       null, // value: create only when required
                                        true // clearAttributes
                                );
                        }
@@ -1243,18 +1764,16 @@ namespace System.Xml
                // character reference or one of the predefined entities.
                // This allows the ReadText method to break so that the
                // next call to Read will return the EntityReference node.
-               private bool ReadReference (bool ignoreEntityReferences)
+               private int ReadReference (bool ignoreEntityReferences)
                {
                        if (PeekChar () == '#') {
                                ReadChar ();
-                               ReadCharacterReference ();
+                               return ReadCharacterReference ();
                        } else
-                               ReadEntityReference (ignoreEntityReferences);
-
-                       return returnEntityReference;
+                               return ReadEntityReference (ignoreEntityReferences);
                }
 
-               private void ReadCharacterReference ()
+               private int ReadCharacterReference ()
                {
                        int value = 0;
 
@@ -1272,9 +1791,9 @@ namespace System.Xml
                                                value = (value << 4) + ch - 'a' + 10;
                                        else
                                                throw new XmlException (this as IXmlLineInfo,
-                                                       String.Format (
+                                                       String.Format (CultureInfo.InvariantCulture, 
                                                                "invalid hexadecimal digit: {0} (#x{1:X})",
-                                                               (char)ch,
+                                                               (char) ch,
                                                                ch));
                                }
                        } else {
@@ -1285,131 +1804,238 @@ namespace System.Xml
                                                value = value * 10 + ch - '0';
                                        else
                                                throw new XmlException (this as IXmlLineInfo,
-                                                       String.Format (
+                                                       String.Format (CultureInfo.InvariantCulture, 
                                                                "invalid decimal digit: {0} (#x{1:X})",
-                                                               (char)ch,
+                                                               (char) ch,
                                                                ch));
                                }
                        }
 
                        ReadChar (); // ';'
 
-                       AppendValueChar (value);
+                       // There is no way to save surrogate pairs...
+                       if (CharacterChecking && XmlChar.IsInvalid (value))
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "Referenced character was not allowed in XML. Normalization is " + normalization + ", checkCharacters = " + checkCharacters);
+                       return value;
                }
 
-               private void ReadEntityReference (bool ignoreEntityReferences)
+               // Returns -1 if it should not be validated.
+               // Real EOF must not be detected here.
+               private int ReadEntityReference (bool ignoreEntityReferences)
                {
-                       nameLength = 0;
-
-                       int ch = PeekChar ();
-
-                       while (ch != ';' && ch != -1) {
-                               AppendNameChar (ReadChar ());
-                               ch = PeekChar ();
-                       }
-
+                       string name = ReadName ();
                        Expect (';');
 
-                       string name = CreateNameString ();
-
-                       switch (name)
-                       {
-                               case "lt":
-                                       AppendValueChar ('<');
-                                       break;
-                               case "gt":
-                                       AppendValueChar ('>');
-                                       break;
-                               case "amp":
+                       int predefined = XmlChar.GetPredefinedEntity (name);
+                       if (predefined >= 0)
+                               return predefined;
+                       else {
+                               if (ignoreEntityReferences) {
                                        AppendValueChar ('&');
-                                       break;
-                               case "apos":
-                                       AppendValueChar ('\'');
-                                       break;
-                               case "quot":
-                                       AppendValueChar ('"');
-                                       break;
-                               default:
-                                       if (ignoreEntityReferences) {
-                                               AppendValueChar ('&');
-
-                                               foreach (char ch2 in name) {
-                                                       AppendValueChar (ch2);
-                                               }
-
-                                               AppendValueChar (';');
-                                       } else {
-                                               returnEntityReference = true;
-                                               entityReferenceName = name;
-                                       }
-                                       break;
+                                       for (int i = 0; i < name.Length; i++)
+                                               AppendValueChar (name [i]);
+                                       AppendValueChar (';');
+                               } else {
+                                       returnEntityReference = true;
+                                       entityReferenceName = name;
+                               }
                        }
+                       return -1;
                }
 
                // The reader is positioned on the first character of
                // the attribute name.
-               private void ReadAttributes (bool allowPIEnd)
+               private void ReadAttributes (bool isXmlDecl)
                {
                        int peekChar = -1;
                        bool requireWhitespace = false;
+                       currentAttribute = -1;
+                       currentAttributeValue = -1;
+
                        do {
                                if (!SkipWhitespace () && requireWhitespace)
                                        throw new XmlException ("Unexpected token. Name is required here.");
-                               string name = ReadName ();
-                               SkipWhitespace ();
-                               Expect ('=');
-                               SkipWhitespace ();
-                               string value = ReadAttribute ();
 
-                               if (name == "xmlns")
-                                       parserContext.NamespaceManager.AddNamespace (String.Empty, UnescapeAttributeValue (value));
-                               else if (name.StartsWith ("xmlns:"))
-                                       parserContext.NamespaceManager.AddNamespace (name.Substring (6), UnescapeAttributeValue (value));
+                               IncrementAttributeToken ();
+                               currentAttributeToken.LineNumber = line;
+                               currentAttributeToken.LinePosition = column;
 
-                               AddAttribute (name, value);
+                               currentAttributeToken.LocalName = 
+                                       currentAttributeToken.Name = ReadName ();
+                               ExpectAfterWhitespace ('=');
+                               SkipWhitespace ();
+                               ReadAttributeValueTokens (-1);
+                               attributeCount++;
+
+                               if (currentAttributeToken.Name == "xmlns")
+                                       parserContext.NamespaceManager.AddNamespace (String.Empty, GetAttribute (currentAttribute));
+                               else if (currentAttributeToken.Name.StartsWith ("xmlns:")) {
+                                       string nsPrefix = currentAttributeToken.Name.Substring (6);
+                                       parserContext.NamespaceManager.AddNamespace (nsPrefix, GetAttribute (currentAttribute));
+                               }
 
-                               if (XmlConstructs.IsSpace (PeekChar ()))
-                                       SkipWhitespace ();
-                               else
+                               if (!SkipWhitespace ())
                                        requireWhitespace = true;
                                peekChar = PeekChar ();
-                               if (peekChar == '?' && allowPIEnd)
+                               if (isXmlDecl) {
+                                       if (peekChar == '?')
+                                               break;
+                               }
+                               else if (peekChar == '/' || peekChar == '>')
                                        break;
-                       } while (peekChar != '/' && peekChar != '>' && peekChar != -1);
+                       } while (peekChar != -1);
+
+                       currentAttribute = -1;
+                       currentAttributeValue = -1;
+               }
+
+               private void AddAttribute (string name, string value)
+               {
+                       IncrementAttributeToken ();
+                       XmlAttributeTokenInfo ati = attributeTokens [currentAttribute];
+                       ati.Name = "SYSTEM";
+                       ati.FillNames ();
+                       IncrementAttributeValueToken ();
+                       XmlTokenInfo vti = attributeValueTokens [currentAttributeValue];
+                       vti.Value = value;
+                       SetProperties (vti, XmlNodeType.Text, String.Empty, false, value, false);
+                       attributeCount++;
+               }
+
+               private void IncrementAttributeToken ()
+               {
+                       currentAttribute++;
+                       if (attributeTokens.Length == currentAttribute) {
+                               XmlAttributeTokenInfo [] newArray = 
+                                       new XmlAttributeTokenInfo [attributeTokens.Length * 2];
+                               attributeTokens.CopyTo (newArray, 0);
+                               attributeTokens = newArray;
+                       }
+                       if (attributeTokens [currentAttribute] == null)
+                               attributeTokens [currentAttribute] = new XmlAttributeTokenInfo (this);
+                       currentAttributeToken = attributeTokens [currentAttribute];
+                       currentAttributeToken.Clear ();
                }
 
-               // The reader is positioned on the quote character.
-               // *Keeps quote char* to value to get_QuoteChar() correctly.
-               private string ReadAttribute ()
+               private void IncrementAttributeValueToken ()
                {
                        ClearValueBuffer ();
+                       currentAttributeValue++;
+                       if (attributeValueTokens.Length == currentAttributeValue) {
+                               XmlTokenInfo [] newArray = new XmlTokenInfo [attributeValueTokens.Length * 2];
+                               attributeValueTokens.CopyTo (newArray, 0);
+                               attributeValueTokens = newArray;
+                       }
+                       if (attributeValueTokens [currentAttributeValue] == null)
+                               attributeValueTokens [currentAttributeValue] = new XmlTokenInfo (this, false);
+                       currentAttributeValueToken = attributeValueTokens [currentAttributeValue];
+                       currentAttributeValueToken.Clear ();
+               }
 
-                       int quoteChar = ReadChar ();
+               // LAMESPEC: Orthodox XML reader should normalize attribute values
+               private void ReadAttributeValueTokens (int dummyQuoteChar)
+               {
+                       int quoteChar = (dummyQuoteChar < 0) ? ReadChar () : dummyQuoteChar;
 
                        if (quoteChar != '\'' && quoteChar != '\"')
                                throw new XmlException (this as IXmlLineInfo,"an attribute value was not quoted");
+                       currentAttributeToken.QuoteChar = (char) quoteChar;
 
-                       AppendValueChar (quoteChar);
+                       IncrementAttributeValueToken ();
+                       currentAttributeToken.ValueTokenStartIndex = currentAttributeValue;
+                       currentAttributeValueToken.LineNumber = line;
+                       currentAttributeValueToken.LinePosition = column;
 
-                       while (PeekChar () != quoteChar) {
-                               int ch = ReadChar ();
+                       bool incrementToken = false;
+                       bool isNewToken = true;
+                       bool loop = true;
+                       int ch = 0;
+                       while (loop) {
+                               ch = ReadChar ();
+                               if (ch == quoteChar)
+                                       break;
+
+                               if (incrementToken) {
+                                       IncrementAttributeValueToken ();
+                                       currentAttributeValueToken.LineNumber = line;
+                                       currentAttributeValueToken.LinePosition = column;
+                                       incrementToken = false;
+                                       isNewToken = true;
+                               }
 
                                switch (ch)
                                {
                                case '<':
                                        throw new XmlException (this as IXmlLineInfo,"attribute values cannot contain '<'");
                                case -1:
-                                       throw new XmlException (this as IXmlLineInfo,"unexpected end of file in an attribute value");
+                                       if (dummyQuoteChar < 0)
+                                               throw new XmlException (this as IXmlLineInfo,"unexpected end of file in an attribute value");
+                                       else    // Attribute value constructor.
+                                               loop = false;
+                                       break;
+                               case '&':
+                                       int startPosition = currentTagLength - 1;
+                                       if (PeekChar () == '#') {
+                                               ReadChar ();
+                                               ch = ReadCharacterReference ();
+                                               if (CharacterChecking && XmlChar.IsInvalid (ch))
+                                                       throw new XmlException (this as IXmlLineInfo,
+                                                               "Not allowed character was found.");
+                                               AppendValueChar (ch);
+                                               break;
+                                       }
+                                       // Check XML 1.0 section 3.1 WFC.
+                                       string entName = ReadName ();
+                                       Expect (';');
+                                       int predefined = XmlChar.GetPredefinedEntity (entName);
+                                       if (predefined < 0) {
+                                               CheckAttributeEntityReferenceWFC (entName);
+                                               currentAttributeValueToken.Value = CreateValueString ();
+                                               currentAttributeValueToken.NodeType = XmlNodeType.Text;
+                                               if (!isNewToken)
+                                                       IncrementAttributeValueToken ();
+                                               currentAttributeValueToken.Name = entName;
+                                               currentAttributeValueToken.Value = String.Empty;
+                                               currentAttributeValueToken.NodeType = XmlNodeType.EntityReference;
+                                               incrementToken = true;
+                                       }
+                                       else
+                                               AppendValueChar (predefined);
+                                       break;
                                default:
+                                       if (CharacterChecking && XmlChar.IsInvalid (ch))
+                                               throw new XmlException (this, "Invalid character was found.");
                                        AppendValueChar (ch);
                                        break;
                                }
+
+                               isNewToken = false;
+                       }
+                       if (!incrementToken) {
+                               currentAttributeValueToken.Value = CreateValueString ();
+                               currentAttributeValueToken.NodeType = XmlNodeType.Text;
                        }
+                       currentAttributeToken.ValueTokenEndIndex = currentAttributeValue;
 
-                       ReadChar (); // quoteChar
-                       AppendValueChar (quoteChar);
+               }
 
-                       return CreateValueString ();
+               private void CheckAttributeEntityReferenceWFC (string entName)
+               {
+                       DTDEntityDeclaration entDecl = 
+                               DTD == null ? null : DTD.EntityDecls [entName];
+                       if (DTD != null && resolver != null && entDecl == null)
+                               throw new XmlException (this, "Referenced entity does not exist.");
+
+                       if (entDecl == null)
+                               return;
+
+                       if (entDecl.HasExternalReference)
+                               throw new XmlException (this, "Reference to external entities is not allowed in the value of an attribute.");
+                       if (isStandalone && !entDecl.IsInternalSubset)
+                               throw new XmlException (this, "Reference to external entities is not allowed in the internal subset.");
+                       if (entDecl.EntityValue.IndexOf ('<') >= 0)
+                               throw new XmlException (this, "Attribute must not contain character '<' either directly or indirectly by way of entity references.");
                }
 
                // The reader is positioned on the first character
@@ -1422,11 +2048,17 @@ namespace System.Xml
                        if (target == "xml") {
                                ReadXmlDeclaration ();
                                return;
-                       }
+                       } else if (target.ToLower (CultureInfo.InvariantCulture) == "xml")
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "Not allowed processing instruction name which starts with 'X', 'M', 'L' was found.");
+
                        if (currentState == XmlNodeType.None)
                                currentState = XmlNodeType.XmlDeclaration;
 
-                       SkipWhitespace ();
+                       if (!SkipWhitespace ())
+                               if (PeekChar () != '?')
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Invalid processing instruction name was found.");
 
                        ClearValueBuffer ();
 
@@ -1438,14 +2070,16 @@ namespace System.Xml
                                        break;
                                }
 
-                               AppendValueChar ((char)ch);
+                               if (CharacterChecking && XmlChar.IsInvalid (ch))
+                                       throw new XmlException (this, "Invalid character was found.");
+                               AppendValueChar (ch);
                        }
 
                        SetProperties (
                                XmlNodeType.ProcessingInstruction, // nodeType
                                target, // name
                                false, // isEmptyElement
-                               valueBuffer, // value
+                               null, // value: create only when required
                                true // clearAttributes
                        );
                }
@@ -1454,30 +2088,139 @@ namespace System.Xml
                private void ReadXmlDeclaration ()
                {
                        if (currentState != XmlNodeType.None) {
-                               if (maybeTextDecl == 0)
-                                       throw new XmlException (this as IXmlLineInfo,
-                                               "XML declaration cannot appear in this state.");
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "XML declaration cannot appear in this state.");
                        }
                        currentState = XmlNodeType.XmlDeclaration;
 
                        ClearAttributes ();
 
                        ReadAttributes (true);  // They must have "version."
-                       Expect ("?>");
+                       string version = GetAttribute ("version");
 
-                       if (maybeTextDecl != 0)
-                               if (this ["standalone"] != null)
-                                       throw new XmlException (this as IXmlLineInfo,
-                                               "Invalid text declaration.");
-                       maybeTextDecl = 0;
+                       string message = null;
+
+                       if (attributeTokens [0].Name != "version" || version != "1.0")
+                               message = "Version 1.0 declaration is required in XML Declaration.";
+                       else if (attributeCount > 1 &&
+                                       (attributeTokens [1].Name != "encoding" &&
+                                       attributeTokens [1].Name != "standalone"))
+                               message = "Invalid Xml Declaration markup was found.";
+                       else if (attributeCount > 2 && attributeTokens [2].Name != "standalone")
+                               message = "Invalid Xml Declaration markup was found.";
+                       string sa = GetAttribute ("standalone");
+                       if (sa != null && sa != "yes" && sa != "no")
+                               message = "Only 'yes' or 'no' is allowed for standalone.";
+
+                       this.isStandalone = (sa == "yes");
+
+                       if (message != null)
+                               throw new XmlException (this as IXmlLineInfo, message);
 
                        SetProperties (
                                XmlNodeType.XmlDeclaration, // nodeType
                                "xml", // name
                                false, // isEmptyElement
-                               currentInput.CurrentMarkup.ToString (6, currentInput.CurrentMarkup.Length - 6), // value
+                               new string (currentTagBuffer, 6, currentTagLength - 6), // value
                                false // clearAttributes
                        );
+
+                       Expect ("?>");
+               }
+
+               internal void SkipTextDeclaration ()
+               {
+                       this.currentState = XmlNodeType.Element;
+
+                       if (PeekChar () != '<')
+                               return;
+
+                       ReadChar ();
+
+                       if (PeekChar () != '?') {
+                               peekCharsIndex = 0;
+                               return;
+                       }
+                       ReadChar ();
+
+                       while (peekCharsIndex < 6) {
+                               if (PeekChar () < 0)
+                                       break;
+                               else
+                                       ReadChar ();
+                       }
+                       if (new string (peekChars, 2, 4) != "xml ") {
+                               if (new string (peekChars, 2, 3).ToLower (CultureInfo.InvariantCulture) == "xml") {
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Processing instruction name must not be character sequence 'X' 'M' 'L' with case insensitivity.");
+                               }
+                               peekCharsIndex = 0;
+                               return;
+                       }
+
+                       SkipWhitespace ();
+
+                       // version decl
+                       if (PeekChar () == 'v') {
+                               Expect ("version");
+                               ExpectAfterWhitespace ('=');
+                               SkipWhitespace ();
+                               int quoteChar = ReadChar ();
+                               char [] expect1_0 = new char [3];
+                               int versionLength = 0;
+                               switch (quoteChar) {
+                               case '\'':
+                               case '"':
+                                       while (PeekChar () != quoteChar) {
+                                               if (PeekChar () == -1)
+                                                       throw new XmlException (this as IXmlLineInfo,
+                                                               "Invalid version declaration inside text declaration.");
+                                               else if (versionLength == 3)
+                                                       throw new XmlException (this as IXmlLineInfo,
+                                                               "Invalid version number inside text declaration.");
+                                               else {
+                                                       expect1_0 [versionLength] = (char) ReadChar ();
+                                                       versionLength++;
+                                                       if (versionLength == 3 && new String (expect1_0) != "1.0")
+                                                               throw new XmlException (this as IXmlLineInfo,
+                                                                       "Invalid version number inside text declaration.");
+                                               }
+                                       }
+                                       ReadChar ();
+                                       SkipWhitespace ();
+                                       break;
+                               default:
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Invalid version declaration inside text declaration.");
+                               }
+                       }
+
+                       if (PeekChar () == 'e') {
+                               Expect ("encoding");
+                               ExpectAfterWhitespace ('=');
+                               SkipWhitespace ();
+                               int quoteChar = ReadChar ();
+                               switch (quoteChar) {
+                               case '\'':
+                               case '"':
+                                       while (PeekChar () != quoteChar)
+                                               if (ReadChar () == -1)
+                                                       throw new XmlException (this as IXmlLineInfo,
+                                                               "Invalid encoding declaration inside text declaration.");
+                                       ReadChar ();
+                                       SkipWhitespace ();
+                                       break;
+                               default:
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Invalid encoding declaration inside text declaration.");
+                               }
+                               // Encoding value should be checked inside XmlInputStream.
+                       }
+                       else
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "Encoding declaration is mandatory in text declaration.");
+
+                       Expect ("?>");
                }
 
                // The reader is positioned on the first character after
@@ -1501,6 +2244,9 @@ namespace System.Xml
                                Expect ("DOCTYPE");
                                ReadDoctypeDecl ();
                                break;
+                       default:
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "Unexpected declaration markup was found.");
                        }
                }
 
@@ -1526,14 +2272,18 @@ namespace System.Xml
                                        break;
                                }
 
-                               AppendValueChar ((char)ch);
+                               if (XmlChar.IsInvalid (ch))
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Not allowed character was found.");
+
+                               AppendValueChar (ch);
                        }
 
                        SetProperties (
                                XmlNodeType.Comment, // nodeType
                                String.Empty, // name
                                false, // isEmptyElement
-                               valueBuffer, // value
+                               null, // value: create only when required
                                true // clearAttributes
                        );
                }
@@ -1563,20 +2313,27 @@ namespace System.Xml
                                                break;
                                        } else {
                                                skip = true;
-//                                             AppendValueChar (']');
-//                                             AppendValueChar (']');
-//                                             ch = ReadChar ();
                                        }
                                }
+                               if (normalization && ch == '\r') {
+                                       ch = PeekChar ();
+                                       if (ch != '\n')
+                                               // append '\n' instead of '\r'.
+                                               AppendValueChar ('\n');
+                                       // otherwise, discard '\r'.
+                                       continue;
+                               }
+                               if (CharacterChecking && XmlChar.IsInvalid (ch))
+                                       throw new XmlException (this, "Invalid character was found.");
 
-                               AppendValueChar ((char)ch);
+                               AppendValueChar (ch);
                        }
 
                        SetProperties (
                                XmlNodeType.CDATA, // nodeType
                                String.Empty, // name
                                false, // isEmptyElement
-                               valueBuffer, // value
+                               null, // value: create only when required
                                true // clearAttributes
                        );
                }
@@ -1585,6 +2342,9 @@ namespace System.Xml
                // the leading '<!DOCTYPE'.
                private void ReadDoctypeDecl ()
                {
+                       if (prohibitDtd)
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "Document Type Declaration (DTD) is prohibited in this XML.");
                        switch (currentState) {
                        case XmlNodeType.DocumentType:
                        case XmlNodeType.Element:
@@ -1595,8 +2355,8 @@ namespace System.Xml
                        currentState = XmlNodeType.DocumentType;
 
                        string doctypeName = null;
-                       string publicId = String.Empty;
-                       string systemId = String.Empty;
+                       string publicId = null;
+                       string systemId = null;
                        int intSubsetStartLine = 0;
                        int intSubsetStartColumn = 0;
 
@@ -1610,7 +2370,9 @@ namespace System.Xml
                                break;
                        case 'P':
                                publicId = ReadPubidLiteral ();
-                               SkipWhitespace ();
+                               if (!SkipWhitespace ())
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Whitespace is required between PUBLIC id and SYSTEM id.");
                                systemId = ReadSystemLiteral (false);
                                break;
                        }
@@ -1623,16 +2385,13 @@ namespace System.Xml
                                ReadChar ();
                                intSubsetStartLine = this.LineNumber;
                                intSubsetStartColumn = this.LinePosition;
-                               int startPos = currentTag.Length;
-                               isIntSubset = true;
+                               int startPos = currentTagLength;
                                ReadInternalSubset ();
-                               isIntSubset = false;
-                               int endPos = currentTag.Length - 1;
-                               parserContext.InternalSubset = currentTag.ToString (startPos, endPos - startPos);
+                               int endPos = currentTagLength - 1;
+                               parserContext.InternalSubset = new string (currentTagBuffer, startPos, endPos - startPos);
                        }
                        // end of DOCTYPE decl.
-                       SkipWhitespace ();
-                       Expect ('>');
+                       ExpectAfterWhitespace ('>');
 
                        GenerateDTDObjectModel (doctypeName, publicId,
                                systemId, parserContext.InternalSubset,
@@ -1646,6 +2405,12 @@ namespace System.Xml
                                parserContext.InternalSubset, // value
                                true // clearAttributes
                                );
+
+                       if (publicId != null)
+                               AddAttribute ("PUBLIC", publicId);
+                       if (systemId != null)
+                               AddAttribute ("SYSTEM", systemId);
+                       currentAttribute = currentAttributeValue = -1;
                }
 
                internal DTDObjectModel GenerateDTDObjectModel (string name, string publicId,
@@ -1658,61 +2423,32 @@ namespace System.Xml
                        string systemId, string internalSubset, int intSubsetStartLine, int intSubsetStartColumn)
                {
                        // now compile DTD
-                       DTD = new DTDObjectModel ();    // merges both internal and external subsets in the meantime,
+                       parserContext.Dtd = new DTDObjectModel (this.NameTable);        // merges both internal and external subsets in the meantime,
+                       DTD.BaseURI = BaseURI;
                        DTD.Name = name;
-                       int originalParserDepth = parserInputStack.Count;
-                       if (internalSubset != null && internalSubset.Length > 0) {
-                               XmlParserInput original = currentInput;
-                               currentInput = new XmlParserInput (new StringReader (internalSubset), BaseURI, intSubsetStartLine, intSubsetStartColumn);
-                               do {
-                                       CompileDTDSubset ();
-                                       if (PeekChar () == -1 && parserInputStack.Count > 0)
-                                               PopParserInput ();
-                               } while (nodeType != XmlNodeType.None || parserInputStack.Count > originalParserDepth);
-                               if (dtdIncludeSect != 0)
-                                       throw new XmlException (this as IXmlLineInfo,"INCLUDE section is not ended correctly.");
-                               currentInput = original;
-                       }
-                       if (systemId != null && systemId != String.Empty && resolver != null) {
-                               PushParserInput (systemId);
-                               do {
-                                       this.CompileDTDSubset ();
-                                       if (PeekChar () == -1 && parserInputStack.Count > 1)
-                                               PopParserInput ();
-                               } while (nodeType != XmlNodeType.None || parserInputStack.Count > originalParserDepth + 1);
-                               PopParserInput ();
-                       }
-
-                       return DTD;
-               }
-
-               private void PushParserInput (string url)
-               {
-                       Uri baseUri = null;
-                       try {
-                               baseUri = new Uri (BaseURI);
-                       } catch (UriFormatException) {
-                       }
+                       DTD.PublicId = publicId;
+                       DTD.SystemId = systemId;
+                       DTD.InternalSubset = internalSubset;
+                       DTD.XmlResolver = resolver;
+                       DTD.IsStandalone = isStandalone;
+                       DTD.LineNumber = line;
+                       DTD.LinePosition = column;
 
-                       Uri absUri = resolver.ResolveUri (baseUri, url);
-                       string absPath = absUri.ToString ();
-
-                       foreach (XmlParserInput i in parserInputStack.ToArray ()) {
-                               if (i.BaseURI == absPath)
-                                       throw new XmlException (this as IXmlLineInfo, "Nested inclusion is not allowed: " + url);
-                       }
-                       parserInputStack.Push (currentInput);
-                       currentInput = new XmlParserInput (new XmlStreamReader (url, false, resolver, BaseURI), absPath);
-                       parserContext.PushScope ();
-                       parserContext.BaseURI = absPath;
-
-                       maybeTextDecl = 2;
+                       DTDReader dr = new DTDReader (DTD, intSubsetStartLine, intSubsetStartColumn);
+                       dr.Normalization = this.normalization;
+#if DTD_HANDLE_EVENTS
+                       dr.ValidationEventHandler += new ValidationEventHandler (OnValidationEvent);
+#endif
+                       return dr.GenerateDTDObjectModel ();
                }
 
-               private void PopParserInput ()
+               private void OnValidationEvent (object o, ValidationEventArgs e)
                {
-                       currentInput = parserInputStack.Pop () as XmlParserInput;
-                       parserContext.PopScope ();
+#if DTD_HANDLE_EVENTS
+                       if (ValidationEventHandler != null)
+                               // Override object as this.
+                               ValidationEventHandler (this, e);
+#endif
                }
 
                private enum DtdInputState
@@ -1781,10 +2517,14 @@ namespace System.Xml
                                case -1:
                                        throw new XmlException (this as IXmlLineInfo,"unexpected end of file at DTD.");
                                case '<':
-                                       if (State == DtdInputState.InsideDoubleQuoted ||
-                                               State == DtdInputState.InsideSingleQuoted)
+                                       switch (State) {
+                                       case DtdInputState.InsideDoubleQuoted:
+                                       case DtdInputState.InsideSingleQuoted:
+                                       case DtdInputState.Comment:
                                                continue;       // well-formed
-                                       switch (ReadChar ()) {
+                                       }
+                                       int c = ReadChar ();
+                                       switch (c) {
                                        case '?':
                                                stateStack.Push (DtdInputState.PI);
                                                break;
@@ -1819,7 +2559,7 @@ namespace System.Xml
                                                }
                                                break;
                                        default:
-                                               throw new XmlException (this as IXmlLineInfo,"unexpected '>'.");
+                                               throw new XmlException (this as IXmlLineInfo, String.Format ("unexpected '<{0}'.", (char) c));
                                        }
                                        break;
                                case '\'':
@@ -1846,9 +2586,7 @@ namespace System.Xml
                                                stateStack.Pop ();
                                                break;
                                        case DtdInputState.InsideDoubleQuoted:
-                                               continue;
                                        case DtdInputState.InsideSingleQuoted:
-                                               continue; // well-formed
                                        case DtdInputState.Comment:
                                                continue;
                                        default:
@@ -1878,798 +2616,66 @@ namespace System.Xml
                        }
                }
 
-               // Read any one of following:
-               //   elementdecl, AttlistDecl, EntityDecl, NotationDecl,
-               //   PI, Comment, Parameter Entity, or doctype termination char(']')
-               //
-               // returns a node of some nodeType or null, setting nodeType.
-               //       (if None then ']' was found.)
-               private void CompileDTDSubset()
+               // The reader is positioned on the first 'S' of "SYSTEM".
+               private string ReadSystemLiteral (bool expectSYSTEM)
                {
-                       SkipWhitespace ();
-                       switch(PeekChar ())
-                       {
-                       case -1:
-                               nodeType = XmlNodeType.None;
-                               break;
-                       case '%':
-                               // It affects on entity references' well-formedness
-                               if (isIntSubset)
-                                       DTD.InternalSubsetHasPEReference = true;
-                               TryExpandPERef ();
-                               break;
-                       case '<':
-                               ReadChar ();
-                               switch(ReadChar ())
-                               {
-                               case '?':
-                                       // Only read, no store.
-                                       ReadProcessingInstruction ();
-                                       break;
-                               case '!':
-                                       CompileDeclaration ();
-                                       break;
-                               default:
-                                       throw new XmlException (this as IXmlLineInfo,"Syntax Error after '<' character.");
-                               }
-                               break;
-                       case ']':
-                               // End of inclusion
-                               Expect ("]]>");
-                               dtdIncludeSect--;
+                       if(expectSYSTEM) {
+                               Expect ("SYSTEM");
+                               if (!SkipWhitespace ())
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Whitespace is required after 'SYSTEM'.");
+                       }
+                       else
                                SkipWhitespace ();
-                               break;
-                       default:
-                               throw new XmlException (this as IXmlLineInfo,String.Format ("Syntax Error inside doctypedecl markup : {0}({1})", PeekChar (), (char) PeekChar ()));
+                       int quoteChar = ReadChar ();    // apos or quot
+                       int startPos = currentTagLength;
+                       int c = 0;
+                       ClearValueBuffer ();
+                       while (c != quoteChar) {
+                               c = ReadChar ();
+                               if (c < 0)
+                                       throw new XmlException (this as IXmlLineInfo,"Unexpected end of stream in ExternalID.");
+                               if (c != quoteChar)
+                                       AppendValueChar (c);
                        }
+                       return CreateValueString ();
                }
 
-               private void CompileDeclaration ()
+               private string ReadPubidLiteral()
                {
-                       nodeType = XmlNodeType.DocumentType;    // Hack!!
-                       switch(ReadChar ())
+                       Expect ("PUBLIC");
+                       if (!SkipWhitespace ())
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "Whitespace is required after 'PUBLIC'.");
+                       int quoteChar = ReadChar ();
+                       int startPos = currentTagLength;
+                       int c = 0;
+                       ClearValueBuffer ();
+                       while(c != quoteChar)
                        {
-                       case '-':
-                               Expect ('-');
-                               // Only read, no store.
-                               ReadComment ();
-                               break;
-                       case 'E':
-                               switch(ReadChar ())
-                               {
-                               case 'N':
-                                       Expect ("TITY");
-                                       SkipWhitespace ();
-                                       LOOPBACK:
-                                       if (PeekChar () == '%') {
-                                               ReadChar ();
-                                               if (!XmlConstructs.IsSpace (PeekChar ())) {
-                                                       ExpandPERef ();
-                                                       goto LOOPBACK;
-//                                                     throw new XmlException (this as IXmlLineInfo,"expected whitespace between '%' and name.");
-                                               } else {
-                                                       SkipWhitespace ();
-                                                       TryExpandPERef ();
-                                                       if (XmlConstructs.IsName (PeekChar ()))
-                                                       ReadParameterEntityDecl ();
-                                                       else
-                                                               throw new XmlException (this as IXmlLineInfo,"expected name character");
-                                               }
-                                               break;
-                                       }
-                                       DTDEntityDeclaration ent = ReadEntityDecl ();
-                                       if (DTD.EntityDecls [ent.Name] == null)
-                                               DTD.EntityDecls.Add (ent.Name, ent);
-                                       break;
-                               case 'L':
-                                       Expect ("EMENT");
-                                       DTDElementDeclaration el = ReadElementDecl ();
-                                       DTD.ElementDecls.Add (el.Name, el);
-                                       break;
-                               default:
-                                       throw new XmlException (this as IXmlLineInfo,"Syntax Error after '<!E' (ELEMENT or ENTITY must be found)");
-                               }
-                               break;
-                       case 'A':
-                               Expect ("TTLIST");
-                               DTDAttListDeclaration atl = ReadAttListDecl ();
-//                             if (DTD.AttListDecls.ContainsKey (atl.Name))
-                                       DTD.AttListDecls.Add (atl.Name, atl);
-                               break;
-                       case 'N':
-                               Expect ("OTATION");
-                               DTDNotationDeclaration not = ReadNotationDecl ();
-                               DTD.NotationDecls.Add (not.Name, not);
-                               break;
-                       case '[':
-                               // conditional sections
-                               SkipWhitespace ();
-                               TryExpandPERef ();
-                               SkipWhitespace ();
-                               Expect ('I');
-                               switch (ReadChar ()) {
-                               case 'N':
-                                       Expect ("CLUDE");
-                                       SkipWhitespace ();
-                                       Expect ('[');
-                                       dtdIncludeSect++;
-                                       break;
-                               case 'G':
-                                       Expect ("NORE");
-                                       ReadIgnoreSect ();
-                                       break;
-                               }
-                               break;
-                       default:
-                               throw new XmlException (this as IXmlLineInfo,"Syntax Error after '<!' characters.");
+                               c = ReadChar ();
+                               if(c < 0) throw new XmlException (this as IXmlLineInfo,"Unexpected end of stream in ExternalID.");
+                               if(c != quoteChar && !XmlChar.IsPubidChar (c))
+                                       throw new XmlException (this as IXmlLineInfo,"character '" + (char) c + "' not allowed for PUBLIC ID");
+                               if (c != quoteChar)
+                                       AppendValueChar (c);
                        }
-               }
-
-               private void ReadIgnoreSect ()
-               {
-                       bool skip = false;
-                       SkipWhitespace ();
-                       Expect ('[');
-                       int dtdIgnoreSect = 1;
-                       while (dtdIgnoreSect > 0) {
-                               switch (skip ? PeekChar () : ReadChar ()) {
-                               case -1:
-                                       throw new XmlException (this as IXmlLineInfo,"Unexpected IGNORE section end.");
-                               case '<':
-                                       if (ReadChar () == '!' && ReadChar () == '[')
-                                               dtdIgnoreSect++;
-                                       break;
-                               case ']':
-                                       if (ReadChar () == ']') {
-                                               if (ReadChar () == '>')
-                                                       dtdIgnoreSect--;
-                                               else
-                                                       skip = true;
-                                       }
-                                       break;
-                               }
-                               skip = false;
-                       }
-               }
-
-               // The reader is positioned on the head of the name.
-               private DTDElementDeclaration ReadElementDecl ()
-               {
-                       DTDElementDeclaration decl = new DTDElementDeclaration (DTD);
-                       SkipWhitespace ();
-                       TryExpandPERef ();
-                       decl.Name = ReadName ();
-                       SkipWhitespace ();
-                       TryExpandPERef ();
-                       ReadContentSpec (decl);
-                       SkipWhitespace ();
-                       // This expanding is only allowed as a non-validating parser.
-                       TryExpandPERef ();
-                       Expect ('>');
-                       return decl;
-               }
-
-               // read 'children'(BNF) of contentspec
-               private void ReadContentSpec (DTDElementDeclaration decl)
-               {
-                       switch(PeekChar ())
-                       {
-                       case 'E':
-                               decl.IsEmpty = true;
-                               Expect ("EMPTY");
-                               break;
-                       case 'A':
-                               decl.IsAny = true;
-                               Expect ("ANY");
-                               break;
-                       case '(':
-                               DTDContentModel model = decl.ContentModel;
-                               ReadChar ();
-                               SkipWhitespace ();
-                               TryExpandPERef ();
-                               if(PeekChar () == '#') {
-                                       // Mixed Contents. "#PCDATA" must appear first.
-                                       decl.IsMixedContent = true;
-                                       Expect ("#PCDATA");
-                                       SkipWhitespace ();
-                                       TryExpandPERef ();
-                                       SkipWhitespace ();
-                                       while(PeekChar () != ')') {
-                                               Expect('|');
-                                               SkipWhitespace ();
-                                               TryExpandPERef ();
-                                               SkipWhitespace ();
-                                               DTDContentModel elem = new DTDContentModel (DTD, decl.Name);
-                                               model.ElementName = ReadName ();
-                                               model.ChildModels.Add (elem);
-                                               SkipWhitespace ();
-                                               TryExpandPERef ();
-                                       }
-                                       Expect (')');
-                                       if (model.ChildModels.Count > 0) {
-                                               Expect ('*');
-                                               model.Occurence = DTDOccurence.ZeroOrMore;
-                                       }
-                                       else if (PeekChar () == '*')
-                                               Expect ('*');
-                               } else {
-                                       // Non-Mixed Contents
-                                       model.ChildModels.Add (ReadCP (decl));
-                                       SkipWhitespace ();
-
-                                       do {    // copied from ReadCP() ...;-)
-                                               TryExpandPERef ();
-                                               SkipWhitespace ();
-                                               if(PeekChar ()=='|') {
-                                                       // CPType=Or
-                                                       model.OrderType = DTDContentOrderType.Or;
-                                                       ReadChar ();
-                                                       SkipWhitespace ();
-                                                       model.ChildModels.Add (ReadCP (decl));
-                                                       SkipWhitespace ();
-                                               }
-                                               else if(PeekChar () == ',')
-                                               {
-                                                       // CPType=Seq
-                                                       model.OrderType = DTDContentOrderType.Seq;
-                                                       ReadChar ();
-                                                       SkipWhitespace ();
-                                                       model.ChildModels.Add (ReadCP (decl));
-                                                       SkipWhitespace ();
-                                               }
-                                               else
-                                                       break;
-                                       }
-                                       while(true);
-
-                                       Expect (')');
-                                       switch(PeekChar ())
-                                       {
-                                       case '?':
-                                               model.Occurence = DTDOccurence.Optional;
-                                               ReadChar ();
-                                               break;
-                                       case '*':
-                                               model.Occurence = DTDOccurence.ZeroOrMore;
-                                               ReadChar ();
-                                               break;
-                                       case '+':
-                                               model.Occurence = DTDOccurence.OneOrMore;
-                                               ReadChar ();
-                                               break;
-                                       }
-                                       SkipWhitespace ();
-                               }
-                               SkipWhitespace ();
-                               break;
-                       }
-               }
-
-               // Read 'cp' (BNF) of contentdecl (BNF)
-               private DTDContentModel ReadCP (DTDElementDeclaration elem)
-               {
-                       DTDContentModel model = null;
-                       TryExpandPERef ();
-                       if(PeekChar () == '(') {
-                               model = new DTDContentModel (DTD, elem.Name);
-                               ReadChar ();
-                               SkipWhitespace ();
-                               model.ChildModels.Add (ReadCP (elem));
-                               SkipWhitespace ();
-                               do {
-                                       TryExpandPERef ();
-                                       SkipWhitespace ();
-                                       if(PeekChar ()=='|') {
-                                               // CPType=Or
-                                               model.OrderType = DTDContentOrderType.Or;
-                                               ReadChar ();
-                                               SkipWhitespace ();
-                                               model.ChildModels.Add (ReadCP (elem));
-                                               SkipWhitespace ();
-                                       }
-                                       else if(PeekChar () == ',') {
-                                               // CPType=Seq
-                                               model.OrderType = DTDContentOrderType.Seq;
-                                               ReadChar ();
-                                               SkipWhitespace ();
-                                               model.ChildModels.Add (ReadCP (elem));
-                                               SkipWhitespace ();
-                                       }
-                                       else
-                                               break;
-                               }
-                               while(true);
-                               SkipWhitespace ();
-                               Expect (')');
-                       }
-                       else {
-                               TryExpandPERef ();
-                               model = new DTDContentModel (DTD, elem.Name);
-                               model.ElementName = ReadName ();
-                       }
-
-                       switch(PeekChar ()) {
-                       case '?':
-                               model.Occurence = DTDOccurence.Optional;
-                               ReadChar ();
-                               break;
-                       case '*':
-                               model.Occurence = DTDOccurence.ZeroOrMore;
-                               ReadChar ();
-                               break;
-                       case '+':
-                               model.Occurence = DTDOccurence.OneOrMore;
-                               ReadChar ();
-                               break;
-                       }
-                       return model;
-               }
-
-               // The reader is positioned on the first name char.
-               private void ReadParameterEntityDecl ()
-               {
-                       DTDParameterEntityDeclaration decl = 
-                               new DTDParameterEntityDeclaration();
-                       decl.BaseURI = BaseURI;
-
-                       decl.Name = ReadName ();
-                       SkipWhitespace ();
-
-                       if (PeekChar () == 'S' || PeekChar () == 'P') {
-//                             throw new NotImplementedException ("External parameter entity reference is not implemented yet.");
-                               // read publicId/systemId
-                               ReadExternalID ();
-                               decl.PublicId = attributes ["PUBLIC"] as string;
-                               decl.SystemId = attributes ["SYSTEM"] as string;
-                               SkipWhitespace ();
-                       }
-                       else {
-                               TryExpandPERef ();
-                               int quoteChar = ReadChar ();
-                               int start = currentTag.Length;
-                               while (true) {
-                                       SkipWhitespace ();
-                                       int c = PeekChar ();
-                                       if ((int) c == -1)
-                                               throw new XmlException ("unexpected end of stream in entity value definition.");
-                                       switch (c) {
-                                       case '"':
-                                               ReadChar ();
-                                               if (quoteChar == '"') goto SKIP;
-                                               break;
-                                       case '\'':
-                                               ReadChar ();
-                                               if (quoteChar == '\'') goto SKIP;
-                                               break;
-                                       case '%':
-                                               ImportAsPERef ();
-                                               break;
-                                       default:
-                                               ReadChar ();
-                                               break;
-                                       }
-                               }
-                               SKIP:
-                               decl.Value = currentTag.ToString (start, currentTag.Length - start - 1);
-                       }
-                       SkipWhitespace ();
-                       Expect ('>');
-                       if (parameterEntities [decl.Name] == null) {
-                                parameterEntities.Add (decl.Name, decl);
-                       }
-               }
-
-               // reader is positioned on '%'
-               private void ImportAsPERef ()
-               {
-                       StringBuilder sb = null;
-                       int peRefStart = currentTag.Length;
-                       string appendStr = "";
-                       ReadChar ();
-                       string peName = ReadName ();
-                       Expect (';');
-                       DTDParameterEntityDeclaration peDecl =
-                               this.parameterEntities [peName] as DTDParameterEntityDeclaration;
-                       if (peDecl == null)
-                               throw new XmlException (this as IXmlLineInfo,"Parameter entity " + peName + " not found.");
-                       if (peDecl.SystemId != null) {
-                               PushParserInput (peDecl.SystemId);
-                               if (sb == null)
-                                       sb = new StringBuilder ();
-                               else
-                                       sb.Length = 0;
-                               while (PeekChar () != -1)
-                                       sb.Append (ReadChar ());
-                               PopParserInput ();
-                               appendStr = sb.ToString ();
-                       } else {
-                               appendStr = peDecl.Value;
-                       }
-                       currentTag.Remove (peRefStart,
-                               currentTag.Length - peRefStart);
-                       currentTag.Append (Dereference (appendStr));
-               }
-
-               // The reader is positioned on the head of the name.
-               private DTDEntityDeclaration ReadEntityDecl ()
-               {
-                       DTDEntityDeclaration decl = new DTDEntityDeclaration ();
-                       decl.IsInternalSubset = isIntSubset;
-                       decl.Name = ReadName ();
-                       SkipWhitespace ();
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-
-                       if (PeekChar () == 'S' || PeekChar () == 'P') {
-                               // external entity
-                               ReadExternalID ();
-                               decl.PublicId = attributes ["PUBLIC"] as string;
-                               decl.SystemId = attributes ["SYSTEM"] as string;
-                               if (SkipWhitespace ()) {
-                                       if (PeekChar () == 'N') {
-                                               // NDataDecl
-                                               Expect ("NDATA");
-                                               if (SkipWhitespace ())
-                                                       decl.NotationName = ReadName ();        // ndata_name
-                                       }
-                               }
-                       }
-                       else {
-                               // general entity
-                               decl.EntityValue = ReadEntityValueDecl ();
-                       }
-                       SkipWhitespace ();
-                       // This expanding is only allowed as a non-validating parser.
-                       TryExpandPERef ();
-                       Expect ('>');
-                       return decl;
-               }
-
-               private string ReadEntityValueDecl ()
-               {
-                       SkipWhitespace ();
-                       // quotation char will be finally removed on unescaping
-                       int quoteChar = ReadChar ();
-                       int start = currentTag.Length;
-                       if (quoteChar != '\'' && quoteChar != '"')
-                               throw new XmlException ("quotation char was expected.");
-
-                       while (PeekChar () != quoteChar) {
-                               switch (PeekChar ()) {
-                               case '%':
-                                       this.ImportAsPERef ();
-                                       continue;
-                               case '&':
-                                       ReadChar ();
-                                       ReadReference (true);
-                                       break;
-                               case -1:
-                                       throw new XmlException ("unexpected end of stream.");
-                               default:
-                                       ReadChar ();
-                                       break;
-                               }
-                       }
-                       string value = Dereference (currentTag.ToString (start, currentTag.Length - start));
-                       Expect (quoteChar);
-                       return value;
-               }
-
-               private DTDAttListDeclaration ReadAttListDecl ()
-               {
-                       SkipWhitespace ();
-                       TryExpandPERef ();
-                       string name = ReadName ();      // target element name
-                       DTDAttListDeclaration decl =
-                               DTD.AttListDecls [name] as DTDAttListDeclaration;
-                       if (decl == null)
-                               decl = new DTDAttListDeclaration ();
-                       decl.Name = name;
-
-                       SkipWhitespace ();
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-
-                       while (XmlConstructs.IsName ((char) PeekChar ())) {
-                               DTDAttributeDefinition def = ReadAttributeDefinition ();
-                               if (decl [def.Name] == null)
-                                       decl.Add (def);
-                               SkipWhitespace ();
-                               TryExpandPERef ();
-                               SkipWhitespace ();
-                       }
-                       SkipWhitespace ();
-                       // This expanding is only allowed as a non-validating parser.
-                       TryExpandPERef ();
-                       Expect ('>');
-                       return decl;
-               }
-
-               private DTDAttributeDefinition ReadAttributeDefinition ()
-               {
-                       DTDAttributeDefinition def = new DTDAttributeDefinition ();
-
-                       // attr_name
-                       TryExpandPERef ();
-                       def.Name = ReadName ();
-                       SkipWhitespace ();
-
-                       // attr_value
-                       TryExpandPERef ();
-                       switch(PeekChar ()) {
-                       case 'C':       // CDATA
-                               Expect ("CDATA");
-                               def.Datatype = XmlSchemaDatatype.FromName ("normalizedString");
-                               break;
-                       case 'I':       // ID, IDREF, IDREFS
-                               Expect ("ID");
-                               if(PeekChar () == 'R') {
-                                       Expect ("REF");
-                                       if(PeekChar () == 'S') {
-                                               // IDREFS
-                                               ReadChar ();
-                                               def.Datatype = XmlSchemaDatatype.FromName ("IDREFS");
-                                       }
-                                       else    // IDREF
-                                               def.Datatype = XmlSchemaDatatype.FromName ("IDREF");
-                               }
-                               else    // ID
-                                       def.Datatype = XmlSchemaDatatype.FromName ("ID");
-                               break;
-                       case 'E':       // ENTITY, ENTITIES
-                               Expect ("ENTIT");
-                               switch(ReadChar ()) {
-                                       case 'Y':       // ENTITY
-                                               def.Datatype = XmlSchemaDatatype.FromName ("ENTITY");
-                                               break;
-                                       case 'I':       // ENTITIES
-                                               Expect ("ES");
-                                               def.Datatype = XmlSchemaDatatype.FromName ("ENTITIES");
-                                               break;
-                               }
-                               break;
-                       case 'N':       // NMTOKEN, NMTOKENS, NOTATION
-                               ReadChar ();
-                               switch(PeekChar ()) {
-                               case 'M':
-                                       Expect ("MTOKEN");
-                                       if(PeekChar ()=='S') {  // NMTOKENS
-                                               ReadChar ();
-                                               def.Datatype = XmlSchemaDatatype.FromName ("NMTOKENS");
-                                       }
-                                       else    // NMTOKEN
-                                               def.Datatype = XmlSchemaDatatype.FromName ("NMTOKEN");
-                                       break;
-                               case 'O':
-                                       Expect ("OTATION");
-                                       def.Datatype = XmlSchemaDatatype.FromName ("NOTATION");
-                                       SkipWhitespace ();
-                                       Expect ('(');
-                                       SkipWhitespace ();
-                                       def.EnumeratedNotations.Add (ReadName ());              // notation name
-                                       SkipWhitespace ();
-                                       while(PeekChar () == '|') {
-                                               ReadChar ();
-                                               SkipWhitespace ();
-                                               def.EnumeratedNotations.Add (ReadName ());      // notation name
-                                               SkipWhitespace ();
-                                       }
-                                       Expect (')');
-                                       break;
-                               default:
-                                       throw new XmlException ("attribute declaration syntax error.");
-                               }
-                               break;
-                       default:        // Enumerated Values
-                               TryExpandPERef ();
-                               Expect ('(');
-                               SkipWhitespace ();
-                               def.EnumeratedAttributeDeclaration.Add (ReadNmToken ());                // enum value
-                               SkipWhitespace ();
-                               while(PeekChar () == '|') {
-                                       ReadChar ();
-                                       SkipWhitespace ();
-                                       def.EnumeratedAttributeDeclaration.Add (ReadNmToken ());        // enum value
-                                       SkipWhitespace ();
-                               }
-                               Expect (')');
-                               break;
-                       }
-                       SkipWhitespace ();
-
-                       TryExpandPERef ();
-
-                       // def_value
-                       if(PeekChar () == '#')
-                       {
-                               ReadChar ();
-                               switch(PeekChar ())
-                               {
-                               case 'R':
-                                       Expect ("REQUIRED");
-                                       def.OccurenceType = DTDAttributeOccurenceType.Required;
-                                       break;
-                               case 'I':
-                                       Expect ("IMPLIED");
-                                       def.OccurenceType = DTDAttributeOccurenceType.Optional;
-                                       break;
-                               case 'F':
-                                       Expect ("FIXED");
-                                       def.OccurenceType = DTDAttributeOccurenceType.Fixed;
-                                       SkipWhitespace ();
-                                       def.UnresolvedDefaultValue = ReadAttribute ();
-                                       break;
-                               }
-                       } else {
-                               // one of the enumerated value
-                               if (PeekChar () == -1) {
-                                       PopParserInput ();
-                               }
-                               SkipWhitespace ();
-                               def.UnresolvedDefaultValue = ReadAttribute ();
-                       }
-
-                       return def;
-               }
-
-               private DTDNotationDeclaration ReadNotationDecl()
-               {
-                       DTDNotationDeclaration decl = new DTDNotationDeclaration ();
-                       SkipWhitespace ();
-                       decl.Name = ReadName ();        // notation name
-                       if (namespaces) {       // copy from SetProperties ;-)
-                               int indexOfColon = decl.Name.IndexOf (':');
-
-                               if (indexOfColon == -1) {
-                                       decl.Prefix = String.Empty;
-                                       decl.LocalName = decl.Name;
-                               } else {
-                                       decl.Prefix = decl.Name.Substring (0, indexOfColon);
-                                       decl.LocalName = decl.Name.Substring (indexOfColon + 1);
-                               }
-                       } else {
-                               decl.Prefix = String.Empty;
-                               decl.LocalName = decl.Name;
-                       }
-
-                       SkipWhitespace ();
-                       if(PeekChar () == 'P') {
-                               decl.PublicId = ReadPubidLiteral ();
-                               SkipWhitespace ();
-                               if (PeekChar () == '\'' || PeekChar () == '"') {
-                                       decl.SystemId = ReadSystemLiteral (false);
-                                       SkipWhitespace ();
-                               }
-                       } else if(PeekChar () == 'S') {
-                               decl.SystemId = ReadSystemLiteral (true);
-                               SkipWhitespace ();
-                       }
-                       if(decl.PublicId == null && decl.SystemId == null)
-                               throw new XmlException ("public or system declaration required for \"NOTATION\" declaration.");
-                       // This expanding is only allowed as a non-validating parser.
-                       TryExpandPERef ();
-                       Expect ('>');
-                       return decl;
-               }
-
-               private void TryExpandPERef ()
-               {
-                       if (PeekChar () == '%') {
-                               ReadChar ();
-                               if (!XmlConstructs.IsName (PeekChar ()))
-                                       return;
-                               ExpandPERef ();
-                       }
-               }
-
-               // reader is positioned on the first letter of the name.
-               private void ExpandPERef ()
-               {
-                       ExpandPERef (true);
-               }
-
-               private void ExpandPERef (bool attachSpace)
-               {
-                       string peName = ReadName ();
-                       Expect (";");
-                       ExpandNamedPERef (peName, attachSpace);
-               }
-
-               private void ExpandNamedPERef (string peName, bool attachSpace)
-               {
-                       DTDParameterEntityDeclaration decl =
-                               parameterEntities [peName] as DTDParameterEntityDeclaration;
-                       if (decl == null)
-                               throw new XmlException ("undeclared parameter entity: '" + peName + "'");
-                       if (decl.SystemId != null) {
-                               PushParserInput (decl.SystemId);
-                       }
-                       // add buffer
-                       else
-                               currentInput.InsertParameterEntityBuffer (attachSpace ? " " + Dereference (decl.Value) + " " : decl.Value);
-                       SkipWhitespace ();      // is it ok?
-//                     while (PeekChar () == '%')
-//                             TryExpandPERef ();      // recursive
-               }
-
-               private void ReadExternalID() {
-                       switch(PeekChar ()) {
-                       case 'S':
-                               attributes ["PUBLIC"] = null;
-                               attributes ["SYSTEM"] = ReadSystemLiteral (true);
-                               break;
-                       case 'P':
-                               attributes ["PUBLIC"] = ReadPubidLiteral ();
-                               SkipWhitespace ();
-                               attributes ["SYSTEM"] = ReadSystemLiteral (false);
-                               break;
-                       }
-               }
-
-               // The reader is positioned on the first 'S' of "SYSTEM".
-               private string ReadSystemLiteral (bool expectSYSTEM)
-               {
-                       if(expectSYSTEM)
-                               Expect ("SYSTEM");
-                       SkipWhitespace ();
-                       int quoteChar = ReadChar ();    // apos or quot
-                       int startPos = currentTag.Length;
-                       int c = 0;
-                       while(c != quoteChar) {
-                               c = ReadChar ();
-                               if(c < 0) throw new XmlException (this as IXmlLineInfo,"Unexpected end of stream in ExternalID.");
-                       }
-                       return currentTag.ToString (startPos, currentTag.Length - 1 - startPos);
-               }
-
-               private string ReadPubidLiteral()
-               {
-                       Expect ("PUBLIC");
-                       SkipWhitespace ();
-                       int quoteChar = ReadChar ();
-                       int startPos = currentTag.Length;
-                       int c = 0;
-                       while(c != quoteChar)
-                       {
-                               c = ReadChar ();
-                               if(c < 0) throw new XmlException (this as IXmlLineInfo,"Unexpected end of stream in ExternalID.");
-                               if(c != quoteChar && !XmlConstructs.IsPubid (c))
-                                       throw new XmlException (this as IXmlLineInfo,"character '" + (char)c + "' not allowed for PUBLIC ID");
-                       }
-                       return currentTag.ToString (startPos, currentTag.Length - 1 - startPos);
+                       return CreateValueString ();
                }
 
                // The reader is positioned on the first character
                // of the name.
-               internal string ReadName ()
-               {
-                       return ReadNameOrNmToken(false);
-               }
-
-               // The reader is positioned on the first character
-               // of the name.
-               private string ReadNmToken ()
-               {
-                       return ReadNameOrNmToken(true);
-               }
-
-               private string ReadNameOrNmToken(bool isNameToken)
+               private string ReadName ()
                {
                        int ch = PeekChar ();
-                       if(isNameToken) {
-                               if (!XmlConstructs.IsName ((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))
-                                       throw new XmlException (this as IXmlLineInfo,String.Format ("a name did not start with a legal character {0} ({1})", ch, (char)ch));
-                       }
+                       if (!XmlChar.IsFirstNameChar (ch))
+                               throw new XmlException (this as IXmlLineInfo,String.Format (CultureInfo.InvariantCulture, "a name did not start with a legal character {0} ({1})", ch, (char) ch));
 
                        nameLength = 0;
 
                        AppendNameChar (ReadChar ());
 
-                       while (XmlConstructs.IsName (PeekChar ())) {
+                       while (XmlChar.IsNameChar (PeekChar ())) {
                                AppendNameChar (ReadChar ());
                        }
 
@@ -2684,11 +2690,11 @@ namespace System.Xml
 
                        if (ch != expected) {
                                throw new XmlException (this as IXmlLineInfo,
-                                       String.Format (
+                                       String.Format (CultureInfo.InvariantCulture, 
                                                "expected '{0}' ({1:X}) but found '{2}' ({3:X})",
-                                               (char)expected,
+                                               (char) expected,
                                                expected,
-                                               (char)ch,
+                                               (char) ch,
                                                ch));
                        }
                }
@@ -2700,17 +2706,30 @@ namespace System.Xml
                                Expect (expected[i]);
                }
 
+               private void ExpectAfterWhitespace (char c)
+               {
+                       while (true) {
+                               int i = ReadChar ();
+                               if (i < 0x21 && XmlChar.IsWhitespace (i))
+                                       continue;
+                               if (c != i)
+                                       throw new XmlException (this, String.Format (CultureInfo.InvariantCulture, "Expected {0}, but found {1} [{2}]", c, (char) i, i));
+                               break;
+                       }
+               }
+
                // Does not consume the first non-whitespace character.
                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 ());
+                       if (!skipped)
+                               return false;
+                       while (XmlChar.IsWhitespace (PeekChar ()))
                                ReadChar ();
                        return skipped;
                }
 
-               private bool ReadWhitespace ()
+               private void ReadWhitespace ()
                {
                        if (currentState == XmlNodeType.None)
                                currentState = XmlNodeType.XmlDeclaration;
@@ -2719,115 +2738,123 @@ 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);
-                       else
-                               SetProperties (XmlNodeType.Whitespace,
+                       else {
+                               XmlNodeType nodeType = (this.XmlSpace == XmlSpace.Preserve) ?
+                                       XmlNodeType.SignificantWhitespace : XmlNodeType.Whitespace;
+                               SetProperties (nodeType,
                                               String.Empty,
                                               false,
-                                              valueBuffer,
+                                              null, // value: create only when required
                                               true);
+                       }
 
-                       return (PeekChar () != -1);
+                       return;
                }
 
-               // read entity reference from attribute string and if parsable then return the value.
-               private string ReadAttributeValueReference ()
+               // Since ReadBase64() is processed for every 4 chars, it does
+               // not handle '=' here.
+               private byte GetBase64Byte (char ch)
                {
-                       int endEntityPosition = attributeString.IndexOf(';',
-                               attributeValuePos);
-                       if (endEntityPosition < 0)
-                               throw new XmlException ("Insufficient markup of entity reference");
-                       string entityName = attributeString.Substring (attributeValuePos + 1,
-                               endEntityPosition - attributeValuePos - 1);
-
-                       attributeValuePos = endEntityPosition + 1;
-
-                       if(entityName [0] == '#') {
-                               char c;
-                               // character entity
-                               if(entityName [1] == 'x') {
-                                       // hexadecimal
-                                       c = (char) int.Parse ("0" + entityName.Substring (2),
-                                               System.Globalization.NumberStyles.HexNumber);
-                               } else {
-                                       // decimal
-                                       c = (char) int.Parse (entityName.Substring (1));
-                               }
-                               return c.ToString();
-                       }
-                       else {
-                               switch(entityName)
-                               {
-                               case "lt": return "<";
-                               case "gt": return ">";
-                               case "amp": return "&";
-                               case "quot": return "\"";
-                               case "apos": return "'";
-                               default: return null;
-                               }
+                       switch (ch) {
+                       case '+':
+                               return 62;
+                       case '/':
+                               return 63;
+                       default:
+                               if (ch >= 'A' && ch <= 'Z')
+                                       return (byte) (ch - 'A');
+                               else if (ch >= 'a' && ch <= 'z')
+                                       return (byte) (ch - 'a' + 26);
+                               else if (ch >= '0' && ch <= '9')
+                                       return (byte) (ch - '0' + 52);
+                               else
+                                       throw new XmlException ("Invalid Base64 character was found.");
                        }
                }
 
-               private string UnescapeAttributeValue (string unresolved)
+               // Returns -1 if it should throw an error.
+               private int ReadCharsInternal (char [] buffer, int offset, int length)
                {
-                       if(unresolved == null) return null;
+                       if (IsEmptyElement) {
+                               Read ();
+                               return 0;
+                       }
 
-                       // trim start/end edge of quotation character.
-                       return Dereference (unresolved.Substring (1, unresolved.Length - 2));
-               }
+                       if (offset < 0)
+                               throw new ArgumentOutOfRangeException ("offset", offset, "Offset must be non-negative integer.");
+                       else if (length < 0)
+                               throw new ArgumentOutOfRangeException ("length", length, "Length must be non-negative integer.");
+                       else if (buffer.Length < offset + length)
+                               throw new ArgumentOutOfRangeException ("buffer length is smaller than the sum of offset and length.");
 
-               private string Dereference (string unresolved)
-               {
-                       StringBuilder resolved = new StringBuilder();
-                       int pos = 0;
-                       int next = unresolved.IndexOf ('&');
-                       if(next < 0)
-                               return unresolved;
+                       if (NodeType != XmlNodeType.Element)
+                               return 0;
 
-                       while(next >= 0) {
-                               if(pos < next)
-                                       resolved.Append (unresolved.Substring (pos, next - pos));// - 1);
-                               int endPos = unresolved.IndexOf (';', next+1);
-                               string entityName =
-                                       unresolved.Substring (next + 1, endPos - next - 1);
-                               if(entityName [0] == '#') {
-                                       char c;
-                                       // character entity
-                                       if(entityName [1] == 'x') {
-                                               // hexadecimal
-                                               c = (char) int.Parse ("0" + entityName.Substring (2),
-                                                       System.Globalization.NumberStyles.HexNumber);
-                                       } else {
-                                               // decimal
-                                               c = (char) int.Parse (entityName.Substring (1));
+                       shouldSkipUntilEndTag = true;
+
+                       int bufIndex = offset;
+                       for (int i = 0; i < length; i++) {
+                               int c = PeekChar ();
+                               switch (c) {
+                               case -1:
+                                       throw new XmlException (this as IXmlLineInfo, "Unexpected end of xml.");
+                               case '<':
+                                       ReadChar ();
+                                       if (PeekChar () != '/') {
+                                               buffer [bufIndex++] = '<';
+                                               continue;
                                        }
-                                       resolved.Append (c);
-                               } else {
-                                       switch(entityName) {
-                                       case "lt": resolved.Append ("<"); break;
-                                       case "gt": resolved.Append (">"); break;
-                                       case "amp": resolved.Append ("&"); break;
-                                       case "quot": resolved.Append ("\""); break;
-                                       case "apos": resolved.Append ("'"); break;
-                                       // With respect to "Value", MS document is helpless
-                                       // and the implemention returns inconsistent value
-                                       // (e.g. XML: "&ent; &amp;ent;" ---> Value: "&ent; &ent;".)
-                                       default: resolved.Append ("&" + entityName + ";"); break;
+                                       // Seems to skip immediate EndElement
+                                       Expect ('/');
+                                       if (depthUp) {
+                                               depth++;
+                                               depthUp = false;
+                                       }
+                                       ReadEndTag ();
+                                       shouldSkipUntilEndTag = false;
+                                       Read (); // move to the next node
+                                       return i;
+                               default:
+                                       ReadChar ();
+                                       if (c < Char.MaxValue)
+                                               buffer [bufIndex++] = (char) c;
+                                       else {
+                                               buffer [bufIndex++] = (char) (c / 0x10000 + 0xD800 - 1);
+                                               buffer [bufIndex++] = (char) (c % 0x10000 + 0xDC00);
                                        }
-                               }
-                               pos = endPos + 1;
-                               if(pos > unresolved.Length)
                                        break;
-                               next = unresolved.IndexOf('&', pos);
+                               }
                        }
-                       resolved.Append (unresolved.Substring(pos));
-
-                       return resolved.ToString();
+                       return length;
                }
 
+               private bool ReadUntilEndTag ()
+               {
+                       int ch;
+                       do {
+                               ch = ReadChar ();
+                               switch (ch) {
+                               case -1:
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Unexpected end of xml.");
+                               case '<':
+                                       if (PeekChar () != '/')
+                                               continue;
+                                       ReadChar ();
+                                       string name = ReadName ();
+                                       if (name != elementNames [elementNameStackPos - 1])
+                                               continue;
+                                       Expect ('>');
+                                       depth--;
+                                       elementNames [--elementNameStackPos] = null;
+                                       return Read ();
+                               }
+                       } while (true);
+               }
                #endregion
        }
 }