2004-10-18 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlTextReader.cs
index 8cabc8e389a25ff827a3485c01bab324fa8043a4..f1d5b59e8b04e5f2364e7c63c64d26bd4fe4522d 100644 (file)
@@ -9,12 +9,30 @@
 // (C) 2001, 2002 Jason Diamond  http://injektilo.org/
 //
 
-// FIXME:
 //
-//   NameTables aren't being used completely yet.
+// 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.
+//
+
+// FIXME:
 //
-//   Some thought needs to be given to performance. There's too many
-//   strings being allocated.
+//   Some thought needs to be given to performance.
 //
 //   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.Collections.Specialized;
+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)
@@ -129,13 +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 elementDepth + 2; // inside attribute value.
+                                       return nodeTypeMod + elementDepth + 2; // inside attribute value.
                                else if (currentAttribute >= 0)
-                                       return elementDepth + 1;
+                                       return nodeTypeMod + elementDepth + 1;
                                return elementDepth;
                        }
                }
@@ -144,88 +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; }
+               }
 
-               public override bool EOF
-               {
-                       get
-                       {
-                               return
-                                       readState == ReadState.EndOfFile ||
-                                       readState == ReadState.Closed;
-                       }
+#if NET_2_0
+               [MonoTODO]
+               public override Evidence Evidence {
+                       get { return base.Evidence; }
                }
+#endif
 
-               public override bool HasValue
-               {
-                       get { 
-                               if (this.valueBuilderAvailable)
-                                       return valueBuilder.Length != 0;
-                               else
-                                       return cursorToken.Value != null;
-                       }
+               public override bool HasValue {
+                       get { return cursorToken.Value != null; }
                }
 
-               public override bool IsDefault
-               {
-                       get
-                       {
-                               // XmlTextReader does not expand default attributes.
-                               return false;
-                       }
+               public override bool IsDefault {
+                       // XmlTextReader does not expand default attributes.
+                       get { return false; }
                }
 
-               public override bool IsEmptyElement
-               {
+               public override bool IsEmptyElement {
                        get { return cursorToken.IsEmptyElement; }
                }
 
-               public override string this [int i]
-               {
+               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
-               {
+               public int LineNumber {
                        get {
                                if (useProceedingLineInfo)
-                                       return currentInput.LineNumber;
+                                       return line;
                                else
                                        return cursorToken.LineNumber;
                        }
                }
 
-               public int LinePosition
-               {
+               public int LinePosition {
                        get {
                                if (useProceedingLineInfo)
-                                       return currentInput.LinePosition;
+                                       return column;
                                else
                                        return cursorToken.LinePosition;
                        }
                }
 
-               public override string LocalName
-               {
+               public override string LocalName {
                        get { return cursorToken.LocalName; }
                }
 
-               public override string Name
-               {
+               public override string Name {
                        get { return cursorToken.Name; }
                }
 
-               public bool Namespaces
-               {
+               public bool Namespaces {
                        get { return namespaces; }
                        set { 
                                if (readState != ReadState.Initial)
@@ -234,66 +271,66 @@ namespace System.Xml
                        }
                }
 
-               public override string 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
-               {
+               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
-               {
+               public override string Prefix {
                        get { return cursorToken.Prefix; }
                }
 
-               public override char QuoteChar
-               {
+#if NET_2_0
+               public bool ProhibitDtd {
+                       get { return prohibitDtd; }
+                       set { prohibitDtd = value; }
+               }
+#endif
+
+               public override char QuoteChar {
                        get { return cursorToken.QuoteChar; }
                }
 
-               public override ReadState ReadState
-               {
+               public override ReadState ReadState {
                        get { return readState; }
                }
 
-               public override string Value
-               {
+#if NET_2_0
+               public override XmlReaderSettings Settings {
+                       get { return base.Settings; }
+               }
+#endif
+
+               public override string Value {
                        get { return cursorToken.Value != null ? cursorToken.Value : String.Empty; }
                }
 
-               public WhitespaceHandling WhitespaceHandling
-               {
+               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; }
                }
 
@@ -304,18 +341,17 @@ 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 > attributeCount)
+                       if (i >= attributeCount)
                                throw new ArgumentOutOfRangeException ("i is smaller than AttributeCount");
                        else {
                                return attributeTokens [i].Value;
@@ -356,22 +392,55 @@ namespace System.Xml
                        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);
+               }
+
+#if NET_2_0
+               public override string LookupNamespace (string prefix, bool atomizedName)
+#else
+               internal override string LookupNamespace (string prefix, bool atomizedName)
+#endif
+               {
+                       return parserContext.NamespaceManager.LookupNamespace (prefix, atomizedName);
+               }
+
+#if NET_2_0
+               string IXmlNamespaceResolver.LookupPrefix (string ns)
+               {
+                       return LookupPrefix (ns, false);
                }
 
+               public string LookupPrefix (string ns, bool atomizedName)
+               {
+                       return parserContext.NamespaceManager.LookupPrefix (ns, atomizedName);
+               }
+#endif
+
                public override void MoveToAttribute (int i)
                {
                        if (i >= attributeCount)
@@ -408,6 +477,9 @@ namespace System.Xml
                        if (currentToken == null)       // for attribute .ctor()
                                return false;
 
+                       if (cursorToken == currentToken)
+                               return false;
+
                        if (currentAttribute >= 0) {
                                currentAttribute = -1;
                                currentAttributeValue = -1;
@@ -456,8 +528,8 @@ namespace System.Xml
 
                        bool more = false;
                        readState = ReadState.Interactive;
-                       currentLinkedNodeLineNumber = currentInput.LineNumber;
-                       currentLinkedNodeLinePosition = currentInput.LinePosition;
+                       currentLinkedNodeLineNumber = line;
+                       currentLinkedNodeLinePosition = column;
                        useProceedingLineInfo = true;
 
                        cursorToken = currentToken;
@@ -466,16 +538,19 @@ namespace System.Xml
                        currentToken.Clear ();
 
                        // It was moved from end of ReadStartTag ().
-                       if (depthUp)
+                       if (depthUp) {
                                ++depth;
-                       depthUp = false;
+                               depthUp = false;
+                       }
 
-                       more = ReadContent ();
+                       if (shouldSkipUntilEndTag) {
+                               shouldSkipUntilEndTag = false;
+                               return ReadUntilEndTag ();
+                       }
 
-                       if (depth == 0 && !allowMultipleRoot && (IsEmptyElement || NodeType == XmlNodeType.EndElement))
-                               currentState = XmlNodeType.EndElement;
-                       if (maybeTextDecl != 0)
-                               maybeTextDecl--;
+                       base64CacheStartsAt = -1;
+
+                       more = ReadContent ();
 
                        if (!more && startNodeType == XmlNodeType.Document && currentState != XmlNodeType.EndElement)
                                throw new XmlException ("Document element did not appear.");
@@ -505,132 +580,282 @@ namespace System.Xml
                                return false;
                }
 
-               [MonoTODO]
+               private int SkipIgnorableBase64Chars (char [] chars, int charsLength, int i)
+               {
+                       while (chars [i] == '=' || XmlChar.IsWhitespace (chars [i]))
+                               if (charsLength == ++i)
+                                       break;
+                       return i;
+               }
+
                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_1_0
+#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 ();
                }
-#endif
 
                public override string ReadString ()
                {
                        return ReadStringInternal ();
                }
+#endif
 
                public void ResetState ()
                {
+                       throw new InvalidOperationException ("Cannot call ResetState when parsing an XML fragment.");
                        Init ();
                }
 
+#if NET_2_0
+               [MonoTODO]
+               public override bool ReadValueAsBoolean ()
+               {
+                       return base.ReadValueAsBoolean ();
+               }
+
+               [MonoTODO]
+               public override DateTime ReadValueAsDateTime ()
+               {
+                       return base.ReadValueAsDateTime ();
+               }
+
+               [MonoTODO]
+               public override decimal ReadValueAsDecimal ()
+               {
+                       return base.ReadValueAsDecimal ();
+               }
+
+               [MonoTODO]
+               public override double ReadValueAsDouble ()
+               {
+                       return base.ReadValueAsDouble ();
+               }
+
+               [MonoTODO]
+               public override int ReadValueAsInt32 ()
+               {
+                       return base.ReadValueAsInt32 ();
+               }
+
+               [MonoTODO]
+               public override long ReadValueAsInt64 ()
+               {
+                       return base.ReadValueAsInt64 ();
+               }
+
+               [MonoTODO]
+               public override ICollection ReadValueAsList ()
+               {
+                       return base.ReadValueAsList ();
+               }
+
+               [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 bool MaybeTextDecl {
-                       set { if (value) this.maybeTextDecl = 2; }
+               internal XmlResolver Resolver {
+                       get { return resolver; }
                }
                #endregion
 
                #region Privates
                internal class XmlTokenInfo
                {
-                       public XmlTokenInfo (XmlTextReader xtr)
+                       public XmlTokenInfo (XmlTextReader xtr, bool isPrimaryToken)
                        {
+                               this.isPrimaryToken = isPrimaryToken;
                                Reader = xtr;
                                Clear ();
                        }
 
+                       bool isPrimaryToken;
                        string valueCache;
 
                        protected XmlTextReader Reader;
@@ -650,15 +875,19 @@ namespace System.Xml
                                get {
                                        if (valueCache != null)
                                                return valueCache;
-                                       else if (Reader.valueBuilderAvailable) {
-                                               valueCache = Reader.valueBuilder.ToString ();
+                                       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 valueCache;
-                               }
-                               set {
-                                       valueCache = value;
+                                       return null;
                                }
+                               set { valueCache = value; }
                        }
 
                        public virtual void Clear ()
@@ -674,28 +903,40 @@ namespace System.Xml
                        internal virtual void FillNames ()
                        {
                                if (Reader.Namespaces) {
-                                       int indexOfColon = Name.IndexOf (':');
+                                       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 {
-                                               Prefix = Reader.NameTable.Add (Name.Substring (0, indexOfColon));
-                                               LocalName = Reader.NameTable.Add (Name.Substring (indexOfColon + 1));
+                                               // 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 == string.Empty)
+                                               if (Prefix.Length == 0)
                                                        NamespaceURI = string.Empty;
                                                else
-                                                       NamespaceURI = Reader.LookupNamespace (Prefix);
+                                                       NamespaceURI = Reader.LookupNamespace (Prefix, true);
                                                break;
 
                                        case XmlNodeType.Element:
                                        case XmlNodeType.EndElement:
-                                               NamespaceURI = Reader.LookupNamespace (Prefix);
+                                               NamespaceURI = Reader.LookupNamespace (Prefix, true);
                                                break;
                                        default:
                                                NamespaceURI = "";
@@ -711,7 +952,7 @@ namespace System.Xml
                internal class XmlAttributeTokenInfo : XmlTokenInfo
                {
                        public XmlAttributeTokenInfo (XmlTextReader reader)
-                               : base (reader)
+                               : base (reader, false)
                        {
                                NodeType = XmlNodeType.Attribute;
                        }
@@ -719,40 +960,49 @@ namespace System.Xml
                        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.Text)
-                                                       valueCache = ti.Value;
-                                               else
+                                               if (ti.NodeType == XmlNodeType.EntityReference)
                                                        valueCache = String.Concat ("&", ti.Name, ";");
+                                               else
+                                                       valueCache = ti.Value;
+                                               if (cachedNormalization)
+                                                       NormalizeSpaces ();
                                                return valueCache;
                                        }
 
-                                       StringBuilder sb = new StringBuilder ();
+                                       tmpBuilder.Length = 0;
                                        for (int i = ValueTokenStartIndex; i <= ValueTokenEndIndex; i++) {
                                                XmlTokenInfo ti = Reader.attributeValueTokens [i];
                                                if (ti.NodeType == XmlNodeType.Text)
-                                                       sb.Append (ti.Value);
+                                                       tmpBuilder.Append (ti.Value);
                                                else {
-                                                       sb.Append ('&');
-                                                       sb.Append (ti.Name);
-                                                       sb.Append (';');
+                                                       tmpBuilder.Append ('&');
+                                                       tmpBuilder.Append (ti.Name);
+                                                       tmpBuilder.Append (';');
                                                }
                                        }
 
-                                       valueCache = sb.ToString ();
-
+                                       valueCache = tmpBuilder.ToString ();
+                                       if (cachedNormalization)
+                                               NormalizeSpaces ();
                                        return valueCache;
                                }
-                               set {
-                                       valueCache = value;
-                               }
+
+                               set { valueCache = value; }
                        }
 
                        public override void Clear ()
@@ -769,6 +1019,26 @@ namespace System.Xml
                                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;
@@ -783,8 +1053,6 @@ namespace System.Xml
 
                private XmlParserContext parserContext;
 
-               private XmlParserInput currentInput;
-               private Stack parserInputStack;
                private ReadState readState;
 
                private int depth;
@@ -792,39 +1060,45 @@ namespace System.Xml
                private bool depthUp;
 
                private bool popScope;
-               private Stack elementStack;
+
+               private string [] elementNames;
+               int elementNameStackPos;
+
                private bool allowMultipleRoot;
 
                private bool isStandalone;
 
-               private StringBuilder valueBuilder;
-               private bool valueBuilderAvailable = false;
-
                private bool returnEntityReference;
                private string entityReferenceName;
 
                private char [] nameBuffer;
                private int nameLength;
                private int nameCapacity;
-               private const int initialNameCapacity = 256;
+               private const int initialNameCapacity = 32;
+
+               private char [] valueBuffer;
+               private int valueLength;
+               private int valueCapacity;
+               private const int initialValueCapacity = 256;
+
+               private char [] currentTagBuffer;
+               private int currentTagLength;
+               private int currentTagCapacity;
+               private const int initialCurrentTagCapacity = 256;
 
-               private StringBuilder valueBuffer;
+               private TextReader reader;
+               private char [] peekChars;
+               private int peekCharsIndex;
+               private int peekCharsLength;
+               private const int peekCharCapacity = 1024;
+
+               private int line;
+               private int column;
 
                private int currentLinkedNodeLineNumber;
                private int currentLinkedNodeLinePosition;
                private bool useProceedingLineInfo;
 
-               // A buffer for ReadContent for ReadOuterXml
-               private StringBuilder currentTag {
-                       get {
-                               return currentInput.CurrentMarkup;
-                       }
-               }
-
-               // Parameter entity placeholder
-               private Hashtable parameterEntities;
-               private int dtdIncludeSect;
-
                private XmlNodeType startNodeType;
                // State machine attribute.
                //      XmlDeclaration: after the first node.
@@ -832,43 +1106,83 @@ namespace System.Xml
                //      Element: inside document element
                //      EndElement: after document element
                private XmlNodeType currentState;
-               private int maybeTextDecl;
 
-               private XmlResolver resolver = new XmlUrlResolver ();
+               // For ReadChars()/ReadBase64()/ReadBinHex()
+               private bool shouldSkipUntilEndTag;
+               private byte [] base64Cache = new byte [3];
+               private int base64CacheStartsAt;
 
                // These values are never re-initialized.
                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();
-                       currentAttribute = -1;
-                       currentAttributeValue = -1;
+                       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 (512);
-                       parameterEntities = new Hashtable ();
 
-                       currentToken = new XmlTokenInfo (this);
-                       cursorToken = currentToken;
+                       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)
@@ -883,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:
-                               fragment = new StringReader (fragment.ReadToEnd ().Replace ("\"", "&quot;"));
+                               reader = new StringReader (fragment.ReadToEnd ().Replace ("\"", "&quot;"));
                                break;
                        case XmlNodeType.Element:
                                currentState = XmlNodeType.Element;
@@ -904,9 +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);
+               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
@@ -933,7 +1275,6 @@ namespace System.Xml
                        string value,
                        bool clearAttributes)
                {
-                       this.valueBuilderAvailable = false;
                        token.Clear ();
                        token.NodeType = nodeType;
                        token.Name = name;
@@ -947,17 +1288,6 @@ namespace System.Xml
                        token.FillNames ();
                }
 
-               private void SetProperties (
-                       XmlNodeType nodeType,
-                       string name,
-                       bool isEmptyElement,
-                       bool clearAttributes,
-                       StringBuilder value) {
-                       SetProperties (nodeType, name, isEmptyElement, (string)null, clearAttributes);
-                       this.valueBuilderAvailable = true;
-                       this.valueBuilder = value;
-               }
-
                private void ClearAttributes ()
                {
                        for (int i = 0; i < attributeCount; i++)
@@ -969,12 +1299,59 @@ namespace System.Xml
 
                private int PeekChar ()
                {
-                       return currentInput.PeekChar ();
+                       if (peekCharsLength == peekCharsIndex) {
+                               if (!ReadTextReader ())
+                                       return -1;
+                               return PeekChar ();
+                       }
+                       else {
+                               char c = peekChars [peekCharsIndex];
+                               if (c != 0) return c;
+                               else return -1;
+                       }
                }
 
                private int ReadChar ()
                {
-                       return currentInput.ReadChar ();
+                       int ch;
+
+                       if (peekCharsLength == peekCharsIndex) {
+                               if (!ReadTextReader ())
+                                       return -1;
+                               return ReadChar ();
+                       }
+                       ch = peekChars [peekCharsIndex++];
+
+                       if (ch == '\n') {
+                               line++;
+                               column = 1;
+                       } else if (ch == 0) {
+                               return -1;
+                       } else {
+                               column++;
+                       }
+                       if (currentState != XmlNodeType.Element)
+                               AppendCurrentTagChar (ch);
+                       return ch;
+               }
+
+               private bool ReadTextReader ()
+               {
+                       peekCharsIndex = 0;
+                       peekCharsLength = reader.Read (peekChars, 0, peekCharCapacity);
+                       if (peekCharsLength == 0)
+                               return false;
+                       return true;
+               }
+
+               private string ExpandSurrogateChar (int ch)
+               {
+                       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
@@ -982,7 +1359,7 @@ 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;
@@ -991,64 +1368,65 @@ namespace System.Xml
                        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)
-                                               ReadWhitespace ();
-                                       else {
-                                               SkipWhitespace ();
-                                               return ReadContent ();
-                                       }
-                                       break;
-                               case -1:
-                                       if (depth > 0)
-                                               throw new XmlException ("unexpected end of file. Current depth is " + depth);
+                               int c = PeekChar ();
+                               if (c == -1) {
                                        readState = ReadState.EndOfFile;
+                                       ClearValueBuffer ();
                                        SetProperties (
                                                XmlNodeType.None, // nodeType
                                                String.Empty, // name
                                                false, // isEmptyElement
-                                               (string) null, // value
+                                               null, // value
                                                true // clearAttributes
                                        );
+                                       if (depth > 0)
+                                               throw new XmlException ("unexpected end of file. Current depth is " + depth);
+
                                        return false;
-                               default:
-                                       ReadText (true);
-                                       break;
+                               } 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;
+                                       }
                                }
                        }
-                       if (NodeType == XmlNodeType.XmlDeclaration && maybeTextDecl == 1)
-                               return ReadContent ();
                        return this.ReadState != ReadState.EndOfFile;
                }
 
                private void SetEntityReferenceProperties ()
                {
-/*
-                       if (resolver != null) {
-                               if (DTD == null)
-                                       throw new XmlException (this as IXmlLineInfo,
-                                               "Entity reference is not allowed without document type declaration.");
-                               else if((!DTD.InternalSubsetHasPEReference || isStandalone) &&
-                                       DTD.EntityDecls [entityReferenceName] == null)
+                       DTDEntityDeclaration decl = DTD != null ? DTD.EntityDecls [entityReferenceName] : null;
+                       if (this.isStandalone)
+                               if (DTD == null || decl == null || !decl.IsInternalSubset)
                                        throw new XmlException (this as IXmlLineInfo,
-                                               "Required entity declaration for '" + entityReferenceName + "' was not found.");
-                               string dummy = DTD.EntityDecls [entityReferenceName].EntityValue;
-                       }
-*/
+                                               "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) null, // value
+                               null, // value
                                true // clearAttributes
                        );
 
@@ -1084,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");
@@ -1107,17 +1488,22 @@ namespace System.Xml
                                attributeTokens [i].FillNames ();
 
                        // quick name check
-                       for (int i = 0; i < attributeCount; i++)
+                       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;
@@ -1137,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) null, // 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
@@ -1160,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;
 
@@ -1177,29 +1589,43 @@ namespace System.Xml
                                XmlNodeType.EndElement, // nodeType
                                name, // name
                                false, // isEmptyElement
-                               (string) null, // 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);
@@ -1207,17 +1633,66 @@ 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;
+               }
+
+               private void AppendCurrentTagChar (int ch)
+               {
+                       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
@@ -1232,44 +1707,54 @@ namespace System.Xml
                                ClearValueBuffer ();
 
                        int ch = PeekChar ();
-                       int previousCloseBracketLine = 0;
-                       int previousCloseBracketColumn = 0;
+                       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 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 (XmlConstructs.IsInvalid (ch))
-                                               throw new XmlException (this as IXmlLineInfo,
-                                                       "Not allowed character was found.");
-                                       AppendValueChar (ReadChar ());
-                                       if (ch == ']') {
-                                               if (previousCloseBracketColumn == LinePosition - 1 &&
-                                                       previousCloseBracketLine == LineNumber)
-                                                       if (PeekChar () == '>')
-                                                               throw new XmlException (this as IXmlLineInfo,
-                                                                       "Inside text content, character sequence ']]>' is not allowed.");
-                                               previousCloseBracketColumn = LinePosition;
-                                               previousCloseBracketLine = LineNumber;
-                                       }
+                                       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 : XmlNodeType.Whitespace;
+                               XmlNodeType nodeType = notWhitespace ? XmlNodeType.Text :
+                                       this.XmlSpace == XmlSpace.Preserve ? XmlNodeType.SignificantWhitespace : XmlNodeType.Whitespace;
                                SetProperties (
                                        nodeType, // nodeType
                                        String.Empty, // name
                                        false, // isEmptyElement
-                                       true, // clearAttributes
-                                       valueBuffer // value
+                                       null, // value: create only when required
+                                       true // clearAttributes
                                );
                        }
                }
@@ -1279,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;
 
@@ -1308,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 {
@@ -1321,62 +1804,49 @@ 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 (); // ';'
 
-                       // FIXME: how to handle such chars larger than 0xffff?
-                       if (value < 0xffff && !XmlConstructs.IsValid (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.");
-                       AppendValueChar (value);
+                                       "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 ();
-                       if (!XmlChar.IsName (name))
-                               throw new XmlException (this as IXmlLineInfo,
-                                       "Invalid entity reference name was found.");
-
-                       char predefined = XmlChar.GetPredefinedEntity (name);
-                       if (predefined != 0)
-                               AppendValueChar (predefined);
+                       int predefined = XmlChar.GetPredefinedEntity (name);
+                       if (predefined >= 0)
+                               return predefined;
                        else {
                                if (ignoreEntityReferences) {
                                        AppendValueChar ('&');
-
-                                       foreach (char ch2 in name) {
-                                               AppendValueChar (ch2);
-                                       }
-
+                                       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 endsWithQuestion)
+               private void ReadAttributes (bool isXmlDecl)
                {
                        int peekChar = -1;
                        bool requireWhitespace = false;
@@ -1388,12 +1858,12 @@ namespace System.Xml
                                        throw new XmlException ("Unexpected token. Name is required here.");
 
                                IncrementAttributeToken ();
-                               currentAttributeToken.LineNumber = currentInput.LineNumber;
-                               currentAttributeToken.LinePosition = currentInput.LinePosition;
+                               currentAttributeToken.LineNumber = line;
+                               currentAttributeToken.LinePosition = column;
 
-                               currentAttributeToken.Name = ReadName ();
-                               SkipWhitespace ();
-                               Expect ('=');
+                               currentAttributeToken.LocalName = 
+                                       currentAttributeToken.Name = ReadName ();
+                               ExpectAfterWhitespace ('=');
                                SkipWhitespace ();
                                ReadAttributeValueTokens (-1);
                                attributeCount++;
@@ -1401,14 +1871,14 @@ namespace System.Xml
                                if (currentAttributeToken.Name == "xmlns")
                                        parserContext.NamespaceManager.AddNamespace (String.Empty, GetAttribute (currentAttribute));
                                else if (currentAttributeToken.Name.StartsWith ("xmlns:")) {
-                                       string nsPrefix = NameTable.Add (currentAttributeToken.Name.Substring (6));
+                                       string nsPrefix = currentAttributeToken.Name.Substring (6);
                                        parserContext.NamespaceManager.AddNamespace (nsPrefix, GetAttribute (currentAttribute));
                                }
 
                                if (!SkipWhitespace ())
                                        requireWhitespace = true;
                                peekChar = PeekChar ();
-                               if (endsWithQuestion) {
+                               if (isXmlDecl) {
                                        if (peekChar == '?')
                                                break;
                                }
@@ -1429,7 +1899,7 @@ namespace System.Xml
                        IncrementAttributeValueToken ();
                        XmlTokenInfo vti = attributeValueTokens [currentAttributeValue];
                        vti.Value = value;
-                       SetProperties (vti, XmlNodeType.Text, name, false, value, false);
+                       SetProperties (vti, XmlNodeType.Text, String.Empty, false, value, false);
                        attributeCount++;
                }
 
@@ -1458,11 +1928,12 @@ namespace System.Xml
                                attributeValueTokens = newArray;
                        }
                        if (attributeValueTokens [currentAttributeValue] == null)
-                               attributeValueTokens [currentAttributeValue] = new XmlTokenInfo (this);
+                               attributeValueTokens [currentAttributeValue] = new XmlTokenInfo (this, false);
                        currentAttributeValueToken = attributeValueTokens [currentAttributeValue];
                        currentAttributeValueToken.Clear ();
                }
 
+               // LAMESPEC: Orthodox XML reader should normalize attribute values
                private void ReadAttributeValueTokens (int dummyQuoteChar)
                {
                        int quoteChar = (dummyQuoteChar < 0) ? ReadChar () : dummyQuoteChar;
@@ -1473,23 +1944,26 @@ namespace System.Xml
 
                        IncrementAttributeValueToken ();
                        currentAttributeToken.ValueTokenStartIndex = currentAttributeValue;
-                       currentAttributeValueToken.LineNumber = currentInput.LineNumber;
-                       currentAttributeValueToken.LinePosition = currentInput.LinePosition;
+                       currentAttributeValueToken.LineNumber = line;
+                       currentAttributeValueToken.LinePosition = column;
 
                        bool incrementToken = false;
                        bool isNewToken = true;
                        bool loop = true;
-                       while (loop && PeekChar () != quoteChar) {
+                       int ch = 0;
+                       while (loop) {
+                               ch = ReadChar ();
+                               if (ch == quoteChar)
+                                       break;
+
                                if (incrementToken) {
                                        IncrementAttributeValueToken ();
-                                       currentAttributeValueToken.LineNumber = currentInput.LineNumber;
-                                       currentAttributeValueToken.LinePosition = currentInput.LinePosition;
+                                       currentAttributeValueToken.LineNumber = line;
+                                       currentAttributeValueToken.LinePosition = column;
                                        incrementToken = false;
                                        isNewToken = true;
                                }
 
-                               int ch = ReadChar ();
-
                                switch (ch)
                                {
                                case '<':
@@ -1501,23 +1975,22 @@ namespace System.Xml
                                                loop = false;
                                        break;
                                case '&':
-                                       int startPosition = currentTag.Length - 1;
+                                       int startPosition = currentTagLength - 1;
                                        if (PeekChar () == '#') {
                                                ReadChar ();
-                                               this.ReadCharacterReference ();
+                                               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) {
-                                               DTDEntityDeclaration entDecl = 
-                                                       DTD == null ? null : DTD.EntityDecls [entName];
-                                               if (entDecl != null && entDecl.SystemId != null)
-//                                             if (!startNodeType == XmlNodeType.Attribute && (entDecl == null || entDecl.SystemId != null))
-                                                       throw new XmlException (this as IXmlLineInfo,
-                                                               "Reference to external entities is not allowed in the value of an attribute.");
+                                       if (predefined < 0) {
+                                               CheckAttributeEntityReferenceWFC (entName);
                                                currentAttributeValueToken.Value = CreateValueString ();
                                                currentAttributeValueToken.NodeType = XmlNodeType.Text;
                                                if (!isNewToken)
@@ -1531,6 +2004,8 @@ namespace System.Xml
                                                AppendValueChar (predefined);
                                        break;
                                default:
+                                       if (CharacterChecking && XmlChar.IsInvalid (ch))
+                                               throw new XmlException (this, "Invalid character was found.");
                                        AppendValueChar (ch);
                                        break;
                                }
@@ -1540,69 +2015,27 @@ namespace System.Xml
                        if (!incrementToken) {
                                currentAttributeValueToken.Value = CreateValueString ();
                                currentAttributeValueToken.NodeType = XmlNodeType.Text;
-                               currentAttributeToken.ValueTokenEndIndex = currentAttributeValue;
                        }
+                       currentAttributeToken.ValueTokenEndIndex = currentAttributeValue;
 
-                       if (dummyQuoteChar < 0)
-                               ReadChar (); // quoteChar
                }
 
-               // The reader is positioned on the quote character.
-               // *Keeps quote char* to value to get_QuoteChar() correctly.
-               // Not it is used only for DTD.
-               private string ReadAttribute (bool isDefaultValue)
+               private void CheckAttributeEntityReferenceWFC (string entName)
                {
-                       ClearValueBuffer ();
-
-                       int quoteChar = ReadChar ();
-
-                       if (quoteChar != '\'' && quoteChar != '\"')
-                               throw new XmlException (this as IXmlLineInfo,"an attribute value was not quoted");
-
-                       AppendValueChar (quoteChar);
-
-                       while (PeekChar () != quoteChar) {
-                               int ch = ReadChar ();
-
-                               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");
-/*
-                               case '&':
-                                       if (isDefaultValue) {
-                                               AppendValueChar (ch);
-                                               break;
-                                       }
-                                       AppendValueChar (ch);
-                                       if (PeekChar () == '#')
-                                               break;
-                                       // Check XML 1.0 section 3.1 WFC.
-                                       string entName = ReadName ();
-                                       Expect (';');
-                                       if (XmlChar.GetPredefinedEntity (entName) == 0) {
-                                               DTDEntityDeclaration entDecl = 
-                                                       DTD == null ? null : DTD.EntityDecls [entName];
-                                               if (entDecl == null || entDecl.SystemId != null)
-                                                       throw new XmlException (this as IXmlLineInfo,
-                                                               "Reference to external entities is not allowed in attribute value.");
-                                       }
-                                       valueBuffer.Append (entName);
-                                       AppendValueChar (';');
-                                       break;
-*/
-                               default:
-                                       AppendValueChar (ch);
-                                       break;
-                               }
-                       }
+                       DTDEntityDeclaration entDecl = 
+                               DTD == null ? null : DTD.EntityDecls [entName];
+                       if (DTD != null && resolver != null && entDecl == null)
+                               throw new XmlException (this, "Referenced entity does not exist.");
 
-                       ReadChar (); // quoteChar
-                       AppendValueChar (quoteChar);
+                       if (entDecl == null)
+                               return;
 
-                       return CreateValueString ();
+                       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
@@ -1615,7 +2048,7 @@ namespace System.Xml
                        if (target == "xml") {
                                ReadXmlDeclaration ();
                                return;
-                       } else if (target.ToLower () == "xml")
+                       } 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.");
 
@@ -1637,15 +2070,17 @@ 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
-                               true, // clearAttributes
-                               valueBuffer // value
+                               null, // value: create only when required
+                               true // clearAttributes
                        );
                }
 
@@ -1653,13 +2088,10 @@ 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.");
                        }
-                       // Is this required?
-                       if (maybeTextDecl != 0)
-                               currentState = XmlNodeType.XmlDeclaration;
+                       currentState = XmlNodeType.XmlDeclaration;
 
                        ClearAttributes ();
 
@@ -1667,113 +2099,192 @@ namespace System.Xml
                        string version = GetAttribute ("version");
 
                        string message = null;
-                       if (parserInputStack.Count == 0) {
-                               if (maybeTextDecl == 0 && (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");
-                       } else {
-                               int currentCheck = 0;
-                               if (attributeTokens [0].Name == "version") {
-                                       if (version != "1.0")
-                                               message = "Version 1.0 declaration is required in Text Declaration.";
-                                       currentCheck = 1;
-                               }
-                               if (attributeCount <= currentCheck || attributeTokens [currentCheck].Name != "encoding")
-                                       message = "Invalid Text Declaration markup was found. encoding specification is required.";
-                       }
-                       if (message != null)
-                               throw new XmlException (this as IXmlLineInfo, message);
 
-                       Expect ("?>");
+                       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.";
 
-                       if (maybeTextDecl != 0)
-                               if (this ["standalone"] != null)
-                                       throw new XmlException (this as IXmlLineInfo,
-                                               "Invalid text declaration.");
-                       if (maybeTextDecl == 2)
-                               maybeTextDecl = 1;
+                       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
                        );
-               }
 
-               // The reader is positioned on the first character after
-               // the leading '<!'.
-               private void ReadDeclaration ()
-               {
-                       int ch = PeekChar ();
-
-                       switch (ch)
-                       {
-                       case '-':
-                               Expect ("--");
-                               ReadComment ();
-                               break;
-                       case '[':
-                               ReadChar ();
-                               Expect ("CDATA[");
-                               ReadCDATA ();
-                               break;
-                       case 'D':
-                               Expect ("DOCTYPE");
-                               ReadDoctypeDecl ();
-                               break;
-                       default:
-                               throw new XmlException (this as IXmlLineInfo,
-                                       "Unexpected declaration markup was found.");
-                       }
+                       Expect ("?>");
                }
 
-               // The reader is positioned on the first character after
-               // the leading '<!--'.
-               private void ReadComment ()
+               internal void SkipTextDeclaration ()
                {
-                       if (currentState == XmlNodeType.None)
-                               currentState = XmlNodeType.XmlDeclaration;
-
-                       ClearValueBuffer ();
+                       this.currentState = XmlNodeType.Element;
 
-                       while (PeekChar () != -1) {
-                               int ch = ReadChar ();
+                       if (PeekChar () != '<')
+                               return;
 
-                               if (ch == '-' && PeekChar () == '-') {
-                                       ReadChar ();
+                       ReadChar ();
 
-                                       if (PeekChar () != '>')
-                                               throw new XmlException (this as IXmlLineInfo,"comments cannot contain '--'");
+                       if (PeekChar () != '?') {
+                               peekCharsIndex = 0;
+                               return;
+                       }
+                       ReadChar ();
 
-                                       ReadChar ();
+                       while (peekCharsIndex < 6) {
+                               if (PeekChar () < 0)
                                        break;
-                               }
-
-                               if (XmlConstructs.IsInvalid (ch))
+                               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,
-                                               "Not allowed character was found.");
-
-                               AppendValueChar ((char)ch);
+                                               "Processing instruction name must not be character sequence 'X' 'M' 'L' with case insensitivity.");
+                               }
+                               peekCharsIndex = 0;
+                               return;
                        }
 
-                       SetProperties (
-                               XmlNodeType.Comment, // nodeType
+                       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
+               // the leading '<!'.
+               private void ReadDeclaration ()
+               {
+                       int ch = PeekChar ();
+
+                       switch (ch)
+                       {
+                       case '-':
+                               Expect ("--");
+                               ReadComment ();
+                               break;
+                       case '[':
+                               ReadChar ();
+                               Expect ("CDATA[");
+                               ReadCDATA ();
+                               break;
+                       case 'D':
+                               Expect ("DOCTYPE");
+                               ReadDoctypeDecl ();
+                               break;
+                       default:
+                               throw new XmlException (this as IXmlLineInfo,
+                                       "Unexpected declaration markup was found.");
+                       }
+               }
+
+               // The reader is positioned on the first character after
+               // the leading '<!--'.
+               private void ReadComment ()
+               {
+                       if (currentState == XmlNodeType.None)
+                               currentState = XmlNodeType.XmlDeclaration;
+
+                       ClearValueBuffer ();
+
+                       while (PeekChar () != -1) {
+                               int ch = ReadChar ();
+
+                               if (ch == '-' && PeekChar () == '-') {
+                                       ReadChar ();
+
+                                       if (PeekChar () != '>')
+                                               throw new XmlException (this as IXmlLineInfo,"comments cannot contain '--'");
+
+                                       ReadChar ();
+                                       break;
+                               }
+
+                               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
-                               true, // clearAttributes
-                               valueBuffer // value
+                               null, // value: create only when required
+                               true // clearAttributes
                        );
                }
 
@@ -1802,21 +2313,28 @@ 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
-                               true, // clearAttributes
-                               valueBuffer // value
+                               null, // value: create only when required
+                               true // clearAttributes
                        );
                }
 
@@ -1824,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:
@@ -1864,14 +2385,13 @@ namespace System.Xml
                                ReadChar ();
                                intSubsetStartLine = this.LineNumber;
                                intSubsetStartColumn = this.LinePosition;
-                               int startPos = currentTag.Length;
+                               int startPos = currentTagLength;
                                ReadInternalSubset ();
-                               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,
@@ -1890,6 +2410,7 @@ namespace System.Xml
                                AddAttribute ("PUBLIC", publicId);
                        if (systemId != null)
                                AddAttribute ("SYSTEM", systemId);
+                       currentAttribute = currentAttributeValue = -1;
                }
 
                internal DTDObjectModel GenerateDTDObjectModel (string name, string publicId,
@@ -1902,67 +2423,32 @@ namespace System.Xml
                        string systemId, string internalSubset, int intSubsetStartLine, int intSubsetStartColumn)
                {
                        // now compile DTD
-                       parserContext.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;
                        DTD.PublicId = publicId;
                        DTD.SystemId = systemId;
                        DTD.InternalSubset = internalSubset;
                        DTD.XmlResolver = resolver;
-                       int originalParserDepth = parserInputStack.Count;
-                       bool more;
-                       if (internalSubset != null && internalSubset.Length > 0) {
-                               XmlParserInput original = currentInput;
-                               currentInput = new XmlParserInput (new StringReader (internalSubset), BaseURI, intSubsetStartLine, intSubsetStartColumn);
-                               do {
-                                       more = CompileDTDSubset ();
-                                       if (PeekChar () == -1 && parserInputStack.Count > 0)
-                                               PopParserInput ();
-                               } while (more || 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 {
-                                       more = this.CompileDTDSubset ();
-                                       if (PeekChar () == -1 && parserInputStack.Count > 1)
-                                               PopParserInput ();
-                               } while (more || parserInputStack.Count > originalParserDepth + 1);
-                               PopParserInput ();
-                       }
-
-                       return DTD;
-               }
-
-               private void PushParserInput (string url)
-               {
-                       Uri baseUri = null;
-                       try {
-                               baseUri = new Uri (BaseURI);
-                       } catch (UriFormatException) {
-                       }
-
-                       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;
+                       DTD.IsStandalone = isStandalone;
+                       DTD.LineNumber = line;
+                       DTD.LinePosition = column;
+
+                       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
@@ -2031,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;
@@ -2069,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 '\'':
@@ -2096,9 +2586,7 @@ namespace System.Xml
                                                stateStack.Pop ();
                                                break;
                                        case DtdInputState.InsideDoubleQuoted:
-                                               continue;
                                        case DtdInputState.InsideSingleQuoted:
-                                               continue; // well-formed
                                        case DtdInputState.Comment:
                                                continue;
                                        default:
@@ -2128,991 +2616,245 @@ namespace System.Xml
                        }
                }
 
-               // Read any one of following:
-               //   elementdecl, AttlistDecl, EntityDecl, NotationDecl,
-               //   PI, Comment, Parameter Entity, or doctype termination char(']')
-               //
-               // Returns true if it may have any more contents, or false if not.
-               private bool CompileDTDSubset()
+               // The reader is positioned on the first 'S' of "SYSTEM".
+               private string ReadSystemLiteral (bool expectSYSTEM)
                {
-                       SkipWhitespace ();
-                       switch(PeekChar ())
-                       {
-                       case -1:
-                               return false;
-                       case '%':
-                               // It affects on entity references' well-formedness
-                               if (this.parserInputStack.Count == 0)
-                                       DTD.InternalSubsetHasPEReference = true;
-                               ReadChar ();
-                               string peName = ReadName ();
-                               Expect (';');
-                               currentInput.InsertParameterEntityBuffer (GetPEValue (peName));
-                               int currentLine = currentInput.LineNumber;
-                               int currentColumn = currentInput.LinePosition;
-                               while (currentInput.HasPEBuffer)
-                                       CompileDTDSubset ();
-                               if (currentInput.LineNumber != currentLine ||
-                                       currentInput.LinePosition != currentColumn)
+                       if(expectSYSTEM) {
+                               Expect ("SYSTEM");
+                               if (!SkipWhitespace ())
                                        throw new XmlException (this as IXmlLineInfo,
-                                               "Incorrectly nested parameter entity.");
-                               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 ']':
-                               if (dtdIncludeSect == 0)
-                                       throw new XmlException (this as IXmlLineInfo, "Unbalanced end of INCLUDE/IGNORE section.");
-                               // End of inclusion
-                               Expect ("]]>");
-                               dtdIncludeSect--;
+                                               "Whitespace is required after 'SYSTEM'.");
+                       }
+                       else
                                SkipWhitespace ();
-                               return false;
-                       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 true;
+                       return CreateValueString ();
                }
 
-               private void CompileDeclaration ()
+               private string ReadPubidLiteral()
                {
-                       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");
-                                       if (!SkipWhitespace ())
-                                               throw new XmlException (this as IXmlLineInfo,
-                                                       "Whitespace is required after '<!ENTITY' in DTD entity declaration.");
-                                       LOOPBACK:
-                                       if (PeekChar () == '%') {
-                                               ReadChar ();
-                                               if (!SkipWhitespace ()) {
-                                                       ImportAsPERef ();
-                                                       goto LOOPBACK;
-                                               } else {
-                                                       TryExpandPERef ();
-                                                       SkipWhitespace ();
-                                                       if (XmlChar.IsNameChar (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);
                        }
+                       return CreateValueString ();
                }
 
-               private void ReadIgnoreSect ()
+               // The reader is positioned on the first character
+               // of the name.
+               private string ReadName ()
                {
-                       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;
+                       int ch = PeekChar ();
+                       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 (XmlChar.IsNameChar (PeekChar ())) {
+                               AppendNameChar (ReadChar ());
                        }
+
+                       return CreateNameString ();
                }
 
-               // The reader is positioned on the head of the name.
-               private DTDElementDeclaration ReadElementDecl ()
+               // Read the next character and compare it against the
+               // specified character.
+               private void Expect (int expected)
                {
-                       DTDElementDeclaration decl = new DTDElementDeclaration (DTD);
-                       if (!SkipWhitespace ())
-                               throw new XmlException (this as IXmlLineInfo,
-                                       "Whitespace is required between '<!ELEMENT' and name in DTD element declaration.");
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-                       decl.Name = ReadName ();
-                       if (!SkipWhitespace ())
+                       int ch = ReadChar ();
+
+                       if (ch != expected) {
                                throw new XmlException (this as IXmlLineInfo,
-                                       "Whitespace is required between name and content in DTD element declaration.");
-                       TryExpandPERef ();
-                       ReadContentSpec (decl);
-                       SkipWhitespace ();
-                       // This expanding is only allowed as a non-validating parser.
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-                       Expect ('>');
-                       return decl;
+                                       String.Format (CultureInfo.InvariantCulture, 
+                                               "expected '{0}' ({1:X}) but found '{2}' ({3:X})",
+                                               (char) expected,
+                                               expected,
+                                               (char) ch,
+                                               ch));
+                       }
                }
 
-               // read 'children'(BNF) of contentspec
-               private void ReadContentSpec (DTDElementDeclaration decl)
+               private void Expect (string expected)
                {
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-                       switch(PeekChar ())
-                       {
-                       case 'E':
-                               decl.IsEmpty = true;
-                               Expect ("EMPTY");
-                               break;
-                       case 'A':
-                               decl.IsAny = true;
-                               Expect ("ANY");
+                       int len = expected.Length;
+                       for(int i=0; i< len; i++)
+                               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;
-                       case '(':
-                               DTDContentModel model = decl.ContentModel;
+                       }
+               }
+
+               // Does not consume the first non-whitespace character.
+               private bool SkipWhitespace ()
+               {
+                       bool skipped = XmlChar.IsWhitespace (PeekChar ());
+                       if (!skipped)
+                               return false;
+                       while (XmlChar.IsWhitespace (PeekChar ()))
                                ReadChar ();
-                               SkipWhitespace ();
-                               TryExpandPERef ();
-                               SkipWhitespace ();
-                               if(PeekChar () == '#') {
-                                       // Mixed Contents. "#PCDATA" must appear first.
-                                       decl.IsMixedContent = true;
-                                       model.Occurence = DTDOccurence.ZeroOrMore;
-                                       model.OrderType = DTDContentOrderType.Or;
-                                       Expect ("#PCDATA");
-                                       SkipWhitespace ();
-                                       TryExpandPERef ();
-                                       SkipWhitespace ();
-                                       while(PeekChar () != ')') {
-                                               Expect('|');
-                                               SkipWhitespace ();
-                                               TryExpandPERef ();
-                                               SkipWhitespace ();
-                                               DTDContentModel elem = new DTDContentModel (DTD, decl.Name);
-                                               elem.ElementName = ReadName ();
-                                               model.ChildModels.Add (elem);
-                                               SkipWhitespace ();
-                                               TryExpandPERef ();
-                                               SkipWhitespace ();
-                                       }
-                                       Expect (')');
-                                       if (model.ChildModels.Count > 0)
-                                               Expect ('*');
-                                       else if (PeekChar () == '*')
-                                               Expect ('*');
-                               } else {
-                                       // Non-Mixed Contents
-                                       model.ChildModels.Add (ReadCP (decl));
-                                       SkipWhitespace ();
-
-                                       do {    // copied from ReadCP() ...;-)
-                                               TryExpandPERef ();
-                                               SkipWhitespace ();
-                                               if(PeekChar ()=='|') {
-                                                       // CPType=Or
-                                                       if (model.OrderType == DTDContentOrderType.Seq)
-                                                               throw new XmlException (this as IXmlLineInfo,
-                                                                       "Inconsistent choice markup in sequence cp.");
-                                                       model.OrderType = DTDContentOrderType.Or;
-                                                       ReadChar ();
-                                                       SkipWhitespace ();
-                                                       model.ChildModels.Add (ReadCP (decl));
-                                                       SkipWhitespace ();
-                                               }
-                                               else if(PeekChar () == ',')
-                                               {
-                                                       // CPType=Seq
-                                                       if (model.OrderType == DTDContentOrderType.Or)
-                                                               throw new XmlException (this as IXmlLineInfo,
-                                                                       "Inconsistent sequence markup in choice cp.");
-                                                       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;
-                       }
+                       return skipped;
                }
 
-               // Read 'cp' (BNF) of contentdecl (BNF)
-               private DTDContentModel ReadCP (DTDElementDeclaration elem)
+               private void ReadWhitespace ()
                {
-                       DTDContentModel model = null;
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-                       if(PeekChar () == '(') {
-                               model = new DTDContentModel (DTD, elem.Name);
-                               ReadChar ();
-                               SkipWhitespace ();
-                               model.ChildModels.Add (ReadCP (elem));
-                               SkipWhitespace ();
-                               do {
-                                       TryExpandPERef ();
-                                       SkipWhitespace ();
-                                       if(PeekChar ()=='|') {
-                                               // CPType=Or
-                                               if (model.OrderType == DTDContentOrderType.Seq)
-                                                       throw new XmlException (this as IXmlLineInfo,
-                                                               "Inconsistent choice markup in sequence cp.");
-                                               model.OrderType = DTDContentOrderType.Or;
-                                               ReadChar ();
-                                               SkipWhitespace ();
-                                               model.ChildModels.Add (ReadCP (elem));
-                                               SkipWhitespace ();
-                                       }
-                                       else if(PeekChar () == ',') {
-                                               // CPType=Seq
-                                               if (model.OrderType == DTDContentOrderType.Or)
-                                                       throw new XmlException (this as IXmlLineInfo,
-                                                               "Inconsistent sequence markup in choice cp.");
-                                               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);
-                               SkipWhitespace ();
-                               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;
-               }
+                       if (currentState == XmlNodeType.None)
+                               currentState = XmlNodeType.XmlDeclaration;
 
-               // The reader is positioned on the first name char.
-               private void ReadParameterEntityDecl ()
-               {
-                       DTDParameterEntityDeclaration decl = 
-                               new DTDParameterEntityDeclaration();
-                       decl.BaseURI = BaseURI;
+                       ClearValueBuffer ();
+                       int ch = PeekChar ();
+                       do {
+                               AppendValueChar (ReadChar ());
+                       } while ((ch = PeekChar ()) != -1 && XmlChar.IsWhitespace (ch));
 
-                       decl.Name = ReadName ();
-                       if (!SkipWhitespace ())
-                               throw new XmlException (this as IXmlLineInfo,
-                                       "Whitespace is required after name in DTD parameter entity declaration.");
-
-                       if (PeekChar () == 'S' || PeekChar () == 'P') {
-//                             throw new NotImplementedException ("External parameter entity reference is not implemented yet.");
-                               // read publicId/systemId
-                               ReadExternalID ();
-                               decl.PublicId = GetAttribute ("PUBLIC");
-                               decl.SystemId = GetAttribute ("SYSTEM");
-                               SkipWhitespace ();
-                               decl.Resolve (resolver);
-                       }
+                       if (currentState == XmlNodeType.Element && ch != -1 && ch != '<')
+                               ReadText (false);
                        else {
-                               TryExpandPERef ();
-                               int quoteChar = ReadChar ();
-                               int start = currentTag.Length;
-                               ClearValueBuffer ();
-                               bool loop = true;
-                               while (loop) {
-                                       int c = PeekChar ();
-                                       switch (c) {
-                                       case -1:
-                                               throw new XmlException ("unexpected end of stream in entity value definition.");
-                                       case '"':
-                                               ReadChar ();
-                                               if (quoteChar == '"')
-                                                       loop = false;
-                                               else
-                                                       AppendValueChar ('"');
-                                               break;
-                                       case '\'':
-                                               ReadChar ();
-                                               if (quoteChar == '\'')
-                                                       loop = false;
-                                               else
-                                                       AppendValueChar ('\'');
-                                               break;
-                                       case '&':
-                                               ReadChar ();
-                                               if (PeekChar () == '#') {
-                                                       ReadChar ();
-                                                       ReadCharacterReference ();
-                                               }
-                                               else
-                                                       AppendValueChar ('&');
-                                               break;
-                                       case '%':
-                                               ReadChar ();
-                                               string peName = ReadName ();
-                                               Expect (';');
-                                               valueBuffer.Append (GetPEValue (peName));
-                                               break;
-                                       default:
-                                               AppendValueChar (ReadChar ());
-                                               break;
-                                       }
-                               }
-                               decl.LiteralValue = CreateValueString (); // currentTag.ToString (start, currentTag.Length - start - 1);
-                               ClearValueBuffer ();
-                       }
-                       SkipWhitespace ();
-                       Expect ('>');
-                       if (parameterEntities [decl.Name] == null) {
-                                parameterEntities.Add (decl.Name, decl);
+                               XmlNodeType nodeType = (this.XmlSpace == XmlSpace.Preserve) ?
+                                       XmlNodeType.SignificantWhitespace : XmlNodeType.Whitespace;
+                               SetProperties (nodeType,
+                                              String.Empty,
+                                              false,
+                                              null, // value: create only when required
+                                              true);
                        }
-               }
 
-               private string GetPEValue (string peName)
-               {
-                       DTDParameterEntityDeclaration peDecl =
-                               this.parameterEntities [peName] as DTDParameterEntityDeclaration;
-                       if (peDecl != null)
-                               return peDecl.Value;
-                       // See XML 1.0 section 4.1 for both WFC and VC.
-                       if ((DTD.SystemId == null && !DTD.InternalSubsetHasPEReference) || this.isStandalone)
-                               throw new XmlException (this as IXmlLineInfo,
-                                       "Parameter entity " + peName + " not found.");
-                       DTD.AddError (new XmlSchemaException (
-                               "Parameter entity " + peName + " not found.", null));
-                       return "";
+                       return;
                }
 
-               private void TryExpandPERef ()
+               // Since ReadBase64() is processed for every 4 chars, it does
+               // not handle '=' here.
+               private byte GetBase64Byte (char ch)
                {
-                       if (PeekChar () == '%') {
-//                             ReadChar ();
-//                             if (!XmlChar.IsNameChar (PeekChar ()))
-//                                     return;
-//                             ExpandPERef ();
-                               ImportAsPERef ();
+                       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.");
                        }
                }
 
-               // reader is positioned on '%'
-               private void ImportAsPERef ()
+               // Returns -1 if it should throw an error.
+               private int ReadCharsInternal (char [] buffer, int offset, int length)
                {
-                       ReadChar ();
-                       string peName = ReadName ();
-                       Expect (';');
-                       DTDParameterEntityDeclaration peDecl =
-                               this.parameterEntities [peName] as DTDParameterEntityDeclaration;
-                       if (peDecl == null) {
-                               DTD.AddError (new XmlSchemaException ("Parameter entity " + peName + " not found.", null));
-                               return; // do nothing
+                       if (IsEmptyElement) {
+                               Read ();
+                               return 0;
                        }
-                       currentInput.InsertParameterEntityBuffer (" " + peDecl.Value + " ");
-
-               }
-
-               // The reader is positioned on the head of the name.
-               private DTDEntityDeclaration ReadEntityDecl ()
-               {
-                       DTDEntityDeclaration decl = new DTDEntityDeclaration (DTD);
-                       decl.IsInternalSubset = (parserInputStack.Count == 0);
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-                       decl.Name = ReadName ();
-                       if (!SkipWhitespace ())
-                               throw new XmlException (this as IXmlLineInfo,
-                                       "Whitespace is required between name and content in DTD entity declaration.");
-                       TryExpandPERef ();
-                       SkipWhitespace ();
 
-                       if (PeekChar () == 'S' || PeekChar () == 'P') {
-                               // external entity
-                               ReadExternalID ();
-                               decl.PublicId = GetAttribute ("PUBLIC");
-                               decl.SystemId = GetAttribute ("SYSTEM");
-                               if (SkipWhitespace ()) {
-                                       if (PeekChar () == 'N') {
-                                               // NDataDecl
-                                               Expect ("NDATA");
-                                               if (!SkipWhitespace ())
-                                                       throw new XmlException (this as IXmlLineInfo,
-                                                               "Whitespace is required after NDATA.");
-                                               decl.NotationName = ReadName ();        // ndata_name
-                                       }
-                               }
-                               decl.ScanEntityValue (new StringCollection ());
-                       }
-                       else {
-                               // literal entity
-                               ReadEntityValueDecl (decl);
-                       }
-                       SkipWhitespace ();
-                       // This expanding is only allowed as a non-validating parser.
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-                       Expect ('>');
-                       return decl;
-               }
+                       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 void ReadEntityValueDecl (DTDEntityDeclaration decl)
-               {
-                       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.");
+                       if (NodeType != XmlNodeType.Element)
+                               return 0;
 
-                       ClearValueBuffer ();
+                       shouldSkipUntilEndTag = true;
 
-                       while (PeekChar () != quoteChar) {
-                               switch (PeekChar ()) {
-                               case '%':
-                                       ReadChar ();
-                                       string name = ReadName ();
-                                       Expect (';');
-                                       if (decl.IsInternalSubset)
-                                               throw new XmlException (this as IXmlLineInfo,
-                                                       "Parameter entity is not allowed in internal subset entity '" + name + "'");
-                                       valueBuffer.Append (GetPEValue (name));
-                                       break;
+                       int bufIndex = offset;
+                       for (int i = 0; i < length; i++) {
+                               int c = PeekChar ();
+                               switch (c) {
                                case -1:
-                                       throw new XmlException ("unexpected end of stream.");
-                               default:
-                                       AppendValueChar (ReadChar ());
-                                       break;
-                               }
-                       }
-                       string value = Dereference (CreateValueString (), false);
-                       ClearValueBuffer ();
-
-                       Expect (quoteChar);
-                       decl.LiteralEntityValue = value;
-               }
-
-               private DTDAttListDeclaration ReadAttListDecl ()
-               {
-                       SkipWhitespace ();
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-                       string name = ReadName ();      // target element name
-                       DTDAttListDeclaration decl =
-                               DTD.AttListDecls [name] as DTDAttListDeclaration;
-                       if (decl == null)
-                               decl = new DTDAttListDeclaration (DTD);
-                       decl.Name = name;
-
-                       if (!SkipWhitespace ())
-                               if (PeekChar () != '>')
-                                       throw new XmlException (this as IXmlLineInfo,
-                                               "Whitespace is required between name and content in non-empty DTD attlist declaration.");
-
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-
-                       while (XmlChar.IsNameChar ((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 ();
-                       SkipWhitespace ();
-                       Expect ('>');
-                       return decl;
-               }
-
-               private DTDAttributeDefinition ReadAttributeDefinition ()
-               {
-                       DTDAttributeDefinition def = new DTDAttributeDefinition ();
-
-                       // attr_name
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-                       def.Name = ReadName ();
-                       if (!SkipWhitespace ())
-                               throw new XmlException (this as IXmlLineInfo,
-                                       "Whitespace is required between name and content in DTD attribute definition.");
-
-                       // attr_value
-                       TryExpandPERef ();
-                       SkipWhitespace ();
-                       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");
+                                       throw new XmlException (this as IXmlLineInfo, "Unexpected end of xml.");
+                               case '<':
+                                       ReadChar ();
+                                       if (PeekChar () != '/') {
+                                               buffer [bufIndex++] = '<';
+                                               continue;
                                        }
-                                       else    // NMTOKEN
-                                               def.Datatype = XmlSchemaDatatype.FromName ("NMTOKEN");
-                                       break;
-                               case 'O':
-                                       Expect ("OTATION");
-                                       def.Datatype = XmlSchemaDatatype.FromName ("NOTATION");
-                                       if (!SkipWhitespace ())
-                                               throw new XmlException (this as IXmlLineInfo,
-                                                       "Whitespace is required between name and content in DTD attribute definition.");
-                                       Expect ('(');
-                                       SkipWhitespace ();
-                                       def.EnumeratedNotations.Add (ReadName ());              // notation name
-                                       SkipWhitespace ();
-                                       while(PeekChar () == '|') {
-                                               ReadChar ();
-                                               SkipWhitespace ();
-                                               def.EnumeratedNotations.Add (ReadName ());      // notation name
-                                               SkipWhitespace ();
+                                       // Seems to skip immediate EndElement
+                                       Expect ('/');
+                                       if (depthUp) {
+                                               depth++;
+                                               depthUp = false;
                                        }
-                                       Expect (')');
-                                       break;
+                                       ReadEndTag ();
+                                       shouldSkipUntilEndTag = false;
+                                       Read (); // move to the next node
+                                       return i;
                                default:
-                                       throw new XmlException ("attribute declaration syntax error.");
-                               }
-                               break;
-                       default:        // Enumerated Values
-                               def.Datatype = XmlSchemaDatatype.FromName ("NMTOKEN");
-                               TryExpandPERef ();
-                               SkipWhitespace ();
-                               Expect ('(');
-                               SkipWhitespace ();
-                               def.EnumeratedAttributeDeclaration.Add (
-                                       def.Datatype.Normalize (ReadNmToken ()));       // enum value
-                               SkipWhitespace ();
-                               while(PeekChar () == '|') {
                                        ReadChar ();
-                                       SkipWhitespace ();
-                                       def.EnumeratedAttributeDeclaration.Add (
-                                               def.Datatype.Normalize (ReadNmToken ()));       // enum value
-                                       SkipWhitespace ();
-                               }
-                               Expect (')');
-                               break;
-                       }
-                       TryExpandPERef ();
-                       if (!SkipWhitespace ())
-                               throw new XmlException (this as IXmlLineInfo,
-                                       "Whitespace is required between type and occurence in DTD attribute definition.");
-
-                       // 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;
-                                       if (!SkipWhitespace ())
-                                               throw new XmlException (this as IXmlLineInfo,
-                                                       "Whitespace is required between FIXED and actual value in DTD attribute definition.");
-                                       def.UnresolvedDefaultValue = ReadAttribute (true);
+                                       if (c < Char.MaxValue)
+                                               buffer [bufIndex++] = (char) c;
+                                       else {
+                                               buffer [bufIndex++] = (char) (c / 0x10000 + 0xD800 - 1);
+                                               buffer [bufIndex++] = (char) (c % 0x10000 + 0xDC00);
+                                       }
                                        break;
                                }
-                       } else {
-                               // one of the enumerated value
-                               TryExpandPERef ();
-                               SkipWhitespace ();
-                               def.UnresolvedDefaultValue = ReadAttribute (true);
-                       }
-
-                       return def;
-               }
-
-               private DTDNotationDeclaration ReadNotationDecl()
-               {
-                       DTDNotationDeclaration decl = new DTDNotationDeclaration ();
-                       TryExpandPERef ();
-                       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 ();
-                               bool wsSkipped = SkipWhitespace ();
-                               if (PeekChar () == '\'' || PeekChar () == '"') {
-                                       if (!wsSkipped)
-                                               throw new XmlException (this as IXmlLineInfo,
-                                                       "Whitespace is required between public id and system id.");
-                                       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 ();
-                       SkipWhitespace ();
-                       Expect ('>');
-                       return decl;
-               }
-
-               private void ReadExternalID () {
-                       this.ClearAttributes ();
-                       switch (PeekChar ()) {
-                       case 'S':
-                               string systemId = ReadSystemLiteral (true);
-                               AddAttribute ("SYSTEM", systemId);
-                               break;
-                       case 'P':
-                               string publicId = ReadPubidLiteral ();
-                               if (!SkipWhitespace ())
-                                       throw new XmlException (this as IXmlLineInfo,
-                                               "Whitespace is required between PUBLIC id and SYSTEM id.");
-                               systemId = ReadSystemLiteral (false);
-                               AddAttribute ("PUBLIC", publicId);
-                               AddAttribute ("SYSTEM", systemId);
-                               break;
-                       }
-               }
-
-               // The reader is positioned on the first 'S' of "SYSTEM".
-               private string ReadSystemLiteral (bool expectSYSTEM)
-               {
-                       if(expectSYSTEM) {
-                               Expect ("SYSTEM");
-                               if (!SkipWhitespace ())
-                                       throw new XmlException (this as IXmlLineInfo,
-                                               "Whitespace is required after 'SYSTEM'.");
-                       }
-                       else
-                               SkipWhitespace ();
-                       int quoteChar = ReadChar ();    // apos or quot
-                       int startPos = currentTag.Length;
-                       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 (); //currentTag.ToString (startPos, currentTag.Length - 1 - startPos);
+                       return length;
                }
 
-               private string ReadPubidLiteral()
+               private bool ReadUntilEndTag ()
                {
-                       Expect ("PUBLIC");
-                       if (!SkipWhitespace ())
-                               throw new XmlException (this as IXmlLineInfo,
-                                       "Whitespace is required after 'PUBLIC'.");
-                       int quoteChar = ReadChar ();
-                       int startPos = currentTag.Length;
-                       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 && !XmlChar.IsPubidChar (c))
-                                       throw new XmlException (this as IXmlLineInfo,"character '" + (char)c + "' not allowed for PUBLIC ID");
-                               if (c != quoteChar)
-                                       AppendValueChar (c);
-                       }
-                       return CreateValueString (); //currentTag.ToString (startPos, currentTag.Length - 1 - startPos);
-               }
-
-               // 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)
-               {
-                       int ch = PeekChar ();
-                       if(isNameToken) {
-                               if (!XmlChar.IsNameChar ((char) ch))
-                                       throw new XmlException (this as IXmlLineInfo,String.Format ("a nmtoken did not start with a legal character {0} ({1})", ch, (char)ch));
-                       }
-                       else {
-                               if (!XmlChar.IsFirstNameChar (ch))
-                                       throw new XmlException (this as IXmlLineInfo,String.Format ("a name did not start with a legal character {0} ({1})", ch, (char)ch));
-                       }
-
-                       nameLength = 0;
-
-                       AppendNameChar (ReadChar ());
-
-                       while (XmlChar.IsNameChar (PeekChar ())) {
-                               AppendNameChar (ReadChar ());
-                       }
-
-                       return CreateNameString ();
-               }
-
-               // Read the next character and compare it against the
-               // specified character.
-               private void Expect (int expected)
-               {
-                       int ch = ReadChar ();
-
-                       if (ch != expected) {
-                               throw new XmlException (this as IXmlLineInfo,
-                                       String.Format (
-                                               "expected '{0}' ({1:X}) but found '{2}' ({3:X})",
-                                               (char)expected,
-                                               expected,
-                                               (char)ch,
-                                               ch));
-                       }
-               }
-
-               private void Expect (string expected)
-               {
-                       int len = expected.Length;
-                       for(int i=0; i< len; i++)
-                               Expect (expected[i]);
-               }
-
-               // Does not consume the first non-whitespace character.
-               private bool SkipWhitespace ()
-               {
-                       //FIXME: Should not skip if whitespaceHandling == WhiteSpaceHandling.None
-                       bool skipped = XmlChar.IsWhitespace (PeekChar ());
-                       while (XmlChar.IsWhitespace (PeekChar ()))
-                               ReadChar ();
-                       return skipped;
-               }
-
-               private void ReadWhitespace ()
-               {
-                       if (currentState == XmlNodeType.None)
-                               currentState = XmlNodeType.XmlDeclaration;
-
-                       ClearValueBuffer ();
-                       int ch = PeekChar ();
+                       int ch;
                        do {
-                               AppendValueChar (ReadChar ());
-                       } while ((ch = PeekChar ()) != -1 && XmlChar.IsWhitespace (ch));
-
-                       if (currentState == XmlNodeType.Element && ch != -1 && ch != '<')
-                               ReadText (false);
-                       else
-                               SetProperties (XmlNodeType.Whitespace,
-                                              String.Empty,
-                                              false,
-                                              true,
-                                              valueBuffer);
-
-                       return; // (PeekChar () != -1);
-               }
-
-               private string Dereference (string unresolved, bool expandPredefined)
-               {
-                       StringBuilder resolved = new StringBuilder();
-                       int pos = 0;
-                       int next = unresolved.IndexOf ('&');
-                       if(next < 0)
-                               return unresolved;
-
-                       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));
-                                       }
-                                       resolved.Append (c);
-                               } else {
-                                       char predefined = XmlChar.GetPredefinedEntity (entityName);
-                                       if (expandPredefined && predefined != 0)
-                                               resolved.Append (predefined);
-                                       else
-                                       // With respect to "Value", MS document is helpless
-                                       // and the implemention returns inconsistent value
-                                       // (e.g. XML: "&ent; &amp;ent;" ---> Value: "&ent; &ent;".)
-                                               resolved.Append ("&" + entityName + ";");
+                               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 ();
                                }
-                               pos = endPos + 1;
-                               if(pos > unresolved.Length)
-                                       break;
-                               next = unresolved.IndexOf('&', pos);
-                       }
-                       resolved.Append (unresolved.Substring(pos));
-
-                       return resolved.ToString();
+                       } while (true);
                }
-
                #endregion
        }
 }