2003-02-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlTextReader.cs
index cc736ed587036736571722c1214e2015de179640..21162130b1893dbfb48b3ebc95d8cfb421fac7c4 100644 (file)
-// -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-\r
-//\r
-// System.Xml.XmlTextReader.cs\r
-//\r
-// Author:\r
-//   Jason Diamond (jason@injektilo.org)\r
-//\r
-// (C) 2001 Jason Diamond  http://injektilo.org/\r
-//\r
-\r
-// FIXME:\r
-//   This can only parse basic XML: elements, attributes, processing\r
-//   instructions, and comments are OK but there's no support for\r
-//   entity/character references or namespaces yet.\r
-//\r
-//   It barfs on DOCTYPE declarations and CDATA sections.\r
-//\r
-//   There's also no checking being done for either well-formedness\r
-//   or validity.\r
-//\r
-//   ParserContext and NameTables aren't being used yet.\r
-//\r
-//   The XmlTextReader-specific properties and methods have yet to\r
-//   be added or implemented.\r
-//\r
-//   Some thought needs to be given to performance. There's too many\r
-//   strings and string builders being allocated.\r
-//\r
-//   None of the MoveTo methods have been implemented yet.\r
-//\r
-//   LineNumber and LinePosition aren't being tracked.\r
-//\r
-//   xml:space, xml:lang, and xml:base aren't being tracked.\r
-//\r
-//   Depth isn't being tracked.\r
-\r
-using System;\r
-using System.Collections;\r
-using System.IO;\r
-using System.Net;\r
-using System.Text;\r
-\r
-namespace System.Xml\r
-{\r
-       public class XmlTextReader : XmlReader\r
-       {\r
-               // constructors\r
-\r
-               protected XmlTextReader()\r
-               {\r
-                       Init();\r
-               }\r
-\r
-               public XmlTextReader(Stream input)\r
-               {\r
-                       Init();\r
-                       reader = new StreamReader(\r
-                               input,\r
-                               Encoding.UTF8,\r
-                               true);\r
-               }\r
-\r
-               public XmlTextReader(string url)\r
-               {\r
-                       Init();\r
-                       WebClient client = new WebClient();\r
-                       reader = new StreamReader(\r
-                               client.OpenRead(url),\r
-                               Encoding.UTF8,\r
-                               true);\r
-               }\r
-\r
-               public XmlTextReader(TextReader input)\r
-               {\r
-                       Init();\r
-                       reader = input;\r
-               }\r
-\r
-               public XmlTextReader(Stream input, XmlNameTable nameTable)\r
-               {\r
-                       // TODO: implement me.\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               public XmlTextReader(string baseURI, Stream input)\r
-               {\r
-                       // TODO: implement me.\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               public XmlTextReader(string baseURI, TextReader input)\r
-               {\r
-                       // TODO: implement me.\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               public XmlTextReader(string url, XmlNameTable nameTable)\r
-               {\r
-                       // TODO: implement me.\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               public XmlTextReader(\r
-                       TextReader input,\r
-                       XmlNameTable nameTable)\r
-               {\r
-                       // TODO: implement me.\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               public XmlTextReader(\r
-                       Stream inputFragment,\r
-                       XmlNodeType fragmentType,\r
-                       XmlParserContext context)\r
-               {\r
-                       // TODO: implement me.\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               public XmlTextReader(\r
-                       string baseURI,\r
-                       Stream input,\r
-                       XmlNameTable nameTable)\r
-               {\r
-                       // TODO: implement me.\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               public XmlTextReader(\r
-                       string baseURI,\r
-                       TextReader input,\r
-                       XmlNameTable nameTable)\r
-               {\r
-                       // TODO: implement me.\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               public XmlTextReader(\r
-                       string fragment,\r
-                       XmlNodeType fragmentType,\r
-                       XmlParserContext context)\r
-               {\r
-                       // TODO: implement me.\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               // properties\r
-\r
-               public override int AttributeCount\r
-               {\r
-                       get\r
-                       {\r
-                               return attributes.Count;\r
-                       }\r
-               }\r
-\r
-               public override string BaseURI\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return null;\r
-                       }\r
-               }\r
-\r
-               public override bool CanResolveEntity\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-               public override int Depth\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return 0;\r
-                       }\r
-               }\r
-\r
-               public override bool EOF\r
-               {\r
-                       get\r
-                       {\r
-                               return\r
-                                       readState == ReadState.EndOfFile ||\r
-                                       readState == ReadState.Closed;\r
-                       }\r
-               }\r
-\r
-               public override bool HasValue\r
-               {\r
-                       get\r
-                       {\r
-                               return value != String.Empty;\r
-                       }\r
-               }\r
-\r
-               public override bool IsDefault\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-               public override bool IsEmptyElement\r
-               {\r
-                       get\r
-                       {\r
-                               return isEmptyElement;\r
-                       }\r
-               }\r
-\r
-               public override string this[int i]\r
-               {\r
-                       get\r
-                       {\r
-                               return GetAttribute(i);\r
-                       }\r
-               }\r
-\r
-               public override string this[string name]\r
-               {\r
-                       get\r
-                       {\r
-                               return GetAttribute(name);\r
-                       }\r
-               }\r
-\r
-               public override string this[\r
-                       string localName,\r
-                       string namespaceName]\r
-               {\r
-                       get\r
-                       {\r
-                               return GetAttribute(localName, namespaceName);\r
-                       }\r
-               }\r
-\r
-               public override string LocalName\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return null;\r
-                       }\r
-               }\r
-\r
-               public override string Name\r
-               {\r
-                       get\r
-                       {\r
-                               return name;\r
-                       }\r
-               }\r
-\r
-               public override string NamespaceURI\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return null;\r
-                       }\r
-               }\r
-\r
-               public override XmlNameTable NameTable\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return null;\r
-                       }\r
-               }\r
-\r
-               public override XmlNodeType NodeType\r
-               {\r
-                       get\r
-                       {\r
-                               return nodeType;\r
-                       }\r
-               }\r
-\r
-               public override string Prefix\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return null;\r
-                       }\r
-               }\r
-\r
-               public override char QuoteChar\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return '"';\r
-                       }\r
-               }\r
-\r
-               public override ReadState ReadState\r
-               {\r
-                       get\r
-                       {\r
-                               return readState;\r
-                       }\r
-               }\r
-\r
-               public override string Value\r
-               {\r
-                       get\r
-                       {\r
-                               return value;\r
-                       }\r
-               }\r
-\r
-               public override string XmlLang\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return null;\r
-                       }\r
-               }\r
-\r
-               public override XmlSpace XmlSpace\r
-               {\r
-                       get\r
-                       {\r
-                               // TODO: implement me.\r
-                               return XmlSpace.Default;\r
-                       }\r
-               }\r
-\r
-               // methods\r
-\r
-               public override void Close()\r
-               {\r
-                       readState = ReadState.Closed;\r
-               }\r
-\r
-               public override string GetAttribute(int i)\r
-               {\r
-                       // TODO: implement me.\r
-                       return null;\r
-               }\r
-\r
-               public override string GetAttribute(string name)\r
-               {\r
-                       return (string)attributes[name];\r
-               }\r
-\r
-               public override string GetAttribute(\r
-                       string localName,\r
-                       string namespaceName)\r
-               {\r
-                       // TODO: implement me.\r
-                       return null;\r
-               }\r
-\r
-               public override string LookupNamespace(string prefix)\r
-               {\r
-                       // TODO: implement me.\r
-                       return null;\r
-               }\r
-\r
-               public override void MoveToAttribute(int i)\r
-               {\r
-                       // TODO: implement me.\r
-               }\r
-\r
-               public override bool MoveToAttribute(string name)\r
-               {\r
-                       // TODO: implement me.\r
-                       return false;\r
-               }\r
-\r
-               public override bool MoveToAttribute(\r
-                       string localName,\r
-                       string namespaceName)\r
-               {\r
-                       // TODO: implement me.\r
-                       return false;\r
-               }\r
-\r
-               public override bool MoveToElement()\r
-               {\r
-                       // TODO: implement me.\r
-                       return false;\r
-               }\r
-\r
-               public override bool MoveToFirstAttribute()\r
-               {\r
-                       // TODO: implement me.\r
-                       return false;\r
-               }\r
-\r
-               public override bool MoveToNextAttribute()\r
-               {\r
-                       // TODO: implement me.\r
-                       return false;\r
-               }\r
-\r
-               public override bool Read()\r
-               {\r
-                       bool more = false;\r
-\r
-                       readState = ReadState.Interactive;\r
-\r
-                       more = ReadContent();\r
-\r
-                       return more;\r
-               }\r
-\r
-               public override bool ReadAttributeValue()\r
-               {\r
-                       // TODO: implement me.\r
-                       return false;\r
-               }\r
-\r
-               public override string ReadInnerXml()\r
-               {\r
-                       // TODO: implement me.\r
-                       return null;\r
-               }\r
-\r
-               public override string ReadOuterXml()\r
-               {\r
-                       // TODO: implement me.\r
-                       return null;\r
-               }\r
-\r
-               public override string ReadString()\r
-               {\r
-                       // TODO: implement me.\r
-                       return null;\r
-               }\r
-\r
-               public override void ResolveEntity()\r
-               {\r
-                       // TODO: implement me.\r
-               }\r
-\r
-               // privates\r
-\r
-               private TextReader reader;\r
-               private ReadState readState;\r
-\r
-               private XmlNodeType nodeType;\r
-               private string name;\r
-               private bool isEmptyElement;\r
-               private string value;\r
-               private Hashtable attributes;\r
-\r
-               private void Init()\r
-               {\r
-                       readState = ReadState.Initial;\r
-\r
-                       nodeType = XmlNodeType.None;\r
-                       name = String.Empty;\r
-                       isEmptyElement = false;\r
-                       value = String.Empty;\r
-                       attributes = new Hashtable();\r
-               }\r
-\r
-               // Use this method rather than setting the properties\r
-               // directly so that all the necessary properties can\r
-               // be changed in harmony with each other. Maybe the\r
-               // fields should be in a seperate class to help enforce\r
-               // this.\r
-               private void SetProperties(\r
-                       XmlNodeType nodeType,\r
-                       string name,\r
-                       bool isEmptyElement,\r
-                       string value,\r
-                       bool clearAttributes)\r
-               {\r
-                       this.nodeType = nodeType;\r
-                       this.name = name;\r
-                       this.isEmptyElement = isEmptyElement;\r
-                       this.value = value;\r
-\r
-                       if (clearAttributes)\r
-                       {\r
-                               ClearAttributes();\r
-                       }\r
-               }\r
-\r
-               private void AddAttribute(string name, string value)\r
-               {\r
-                       attributes.Add(name, value);\r
-               }\r
-\r
-               private void ClearAttributes()\r
-               {\r
-                       attributes.Clear();\r
-               }\r
-\r
-               // This should really keep track of some state so\r
-               // that it's not possible to have more than one document\r
-               // element or text outside of the document element.\r
-               private bool ReadContent()\r
-               {\r
-                       bool more = false;\r
-\r
-                       switch (reader.Peek())\r
-                       {\r
-                       case '<':\r
-                               reader.Read();\r
-                               ReadTag();\r
-                               more = true;\r
-                               break;\r
-                       case -1:\r
-                               readState = ReadState.EndOfFile;\r
-                               SetProperties(\r
-                                       XmlNodeType.None, // nodeType\r
-                                       String.Empty, // name\r
-                                       false, // isEmptyElement\r
-                                       String.Empty, // value\r
-                                       true // clearAttributes\r
-                               );\r
-                               more = false;\r
-                               break;\r
-                       default:\r
-                               ReadText();\r
-                               more = true;\r
-                               break;\r
-                       }\r
-\r
-                       return more;\r
-               }\r
-\r
-               // The leading '<' has already been consumed.\r
-               private void ReadTag()\r
-               {\r
-                       switch (reader.Peek())\r
-                       {\r
-                       case '/':\r
-                               reader.Read();\r
-                               ReadEndTag();\r
-                               break;\r
-                       case '?':\r
-                               reader.Read();\r
-                               ReadProcessingInstruction();\r
-                               break;\r
-                       case '!':\r
-                               reader.Read();\r
-                               ReadComment();\r
-                               break;\r
-                       default:\r
-                               ReadStartTag();\r
-                               break;\r
-                       }\r
-               }\r
-\r
-               // The leading '<' has already been consumed.\r
-               private void ReadStartTag()\r
-               {\r
-                       string name = ReadName();\r
-                       SkipWhitespace();\r
-\r
-                       bool isEmptyElement = false;\r
-\r
-                       ClearAttributes();\r
-\r
-                       if (XmlChar.IsFirstNameChar(reader.Peek()))\r
-                       {\r
-                               ReadAttributes();\r
-                       }\r
-\r
-                       if (reader.Peek() == '/')\r
-                       {\r
-                               reader.Read();\r
-                               isEmptyElement = true;\r
-                       }\r
-\r
-                       Expect('>');\r
-\r
-                       SetProperties(\r
-                               XmlNodeType.Element, // nodeType\r
-                               name, // name\r
-                               isEmptyElement, // isEmptyElement\r
-                               String.Empty, // value\r
-                               false // clearAttributes\r
-                       );\r
-               }\r
-\r
-               // The reader is positioned on the first character\r
-               // of the element's name.\r
-               private void ReadEndTag()\r
-               {\r
-                       string name = ReadName();\r
-                       SkipWhitespace();\r
-                       Expect('>');\r
-\r
-                       SetProperties(\r
-                               XmlNodeType.EndElement, // nodeType\r
-                               name, // name\r
-                               false, // isEmptyElement\r
-                               String.Empty, // value\r
-                               true // clearAttributes\r
-                       );\r
-               }\r
-\r
-               // The reader is positioned on the first character\r
-               // of the text.\r
-               private void ReadText()\r
-               {\r
-                       StringBuilder text = new StringBuilder();\r
-                       text.Append((char)reader.Read());\r
-\r
-                       while (reader.Peek() != '<' && reader.Peek() != -1)\r
-                       {\r
-                               text.Append((char)reader.Read());\r
-                       }\r
-\r
-                       SetProperties(\r
-                               XmlNodeType.Text, // nodeType\r
-                               String.Empty, // name\r
-                               false, // isEmptyElement\r
-                               text.ToString(), // value\r
-                               true // clearAttributes\r
-                       );\r
-               }\r
-\r
-               // The reader is positioned on the first character of\r
-               // the attribute name.\r
-               private void ReadAttributes()\r
-               {\r
-                       do\r
-                       {\r
-                               string name = ReadName();\r
-                               SkipWhitespace();\r
-                               Expect('=');\r
-                               SkipWhitespace();\r
-                               string value = ReadAttribute();\r
-                               SkipWhitespace();\r
-\r
-                               AddAttribute(name, value);\r
-                       }\r
-                       while (reader.Peek() != '/' && reader.Peek() != '>' && reader.Peek() != -1);\r
-               }\r
-\r
-               // The reader is positioned on the quote character.\r
-               private string ReadAttribute()\r
-               {\r
-                       int quoteChar = reader.Read();\r
-\r
-                       if (quoteChar != '\'' && quoteChar != '\"')\r
-                       {\r
-                               throw new Exception("an attribute value was not quoted");\r
-                       }\r
-\r
-                       StringBuilder valueBuilder = new StringBuilder();\r
-\r
-                       while (reader.Peek() != quoteChar)\r
-                       {\r
-                               int ch = reader.Read();\r
-\r
-                               switch (ch)\r
-                               {\r
-                               case '<':\r
-                                       throw new Exception("attribute values cannot contain '<'");\r
-                               case -1:\r
-                                       throw new Exception("unexpected end of file in an attribute value");\r
-                               }\r
-\r
-                               valueBuilder.Append((char)ch);\r
-                       }\r
-\r
-                       reader.Read();\r
-\r
-                       return valueBuilder.ToString();\r
-               }\r
-\r
-               // The reader is positioned on the first character\r
-               // of the target.\r
-               private void ReadProcessingInstruction()\r
-               {\r
-                       string target = ReadName();\r
-                       SkipWhitespace();\r
-\r
-                       StringBuilder valueBuilder = new StringBuilder();\r
-\r
-                       while (reader.Peek() != -1)\r
-                       {\r
-                               int ch = reader.Read();\r
-\r
-                               if (ch == '?' && reader.Peek() == '>')\r
-                               {\r
-                                       reader.Read();\r
-                                       break;\r
-                               }\r
-\r
-                               valueBuilder.Append((char)ch);\r
-                       }\r
-\r
-                       SetProperties(\r
-                               XmlNodeType.ProcessingInstruction, // nodeType\r
-                               target, // name\r
-                               false, // isEmptyElement\r
-                               valueBuilder.ToString(), // value\r
-                               true // clearAttributes\r
-                       );\r
-               }\r
-\r
-               // The reader is positioned on the first character after\r
-               // the leading '<!'.\r
-               private void ReadComment()\r
-               {\r
-                       Expect('-');\r
-                       Expect('-');\r
-\r
-                       StringBuilder valueBuilder = new StringBuilder();\r
-\r
-                       while (reader.Peek() != -1)\r
-                       {\r
-                               int ch = reader.Read();\r
-\r
-                               if (ch == '-' && reader.Peek() == '-')\r
-                               {\r
-                                       reader.Read();\r
-\r
-                                       if (reader.Peek() != '>')\r
-                                       {\r
-                                               throw new Exception("comments cannot contain '--'");\r
-                                       }\r
-\r
-                                       reader.Read();\r
-                                       break;\r
-                               }\r
-\r
-                               valueBuilder.Append((char)ch);\r
-                       }\r
-\r
-                       SetProperties(\r
-                               XmlNodeType.Comment, // nodeType\r
-                               String.Empty, // name\r
-                               false, // isEmptyElement\r
-                               valueBuilder.ToString(), // value\r
-                               true // clearAttributes\r
-                       );\r
-               }\r
-\r
-               // The reader is positioned on the first character\r
-               // of the name.\r
-               private string ReadName()\r
-               {\r
-                       if (!XmlChar.IsFirstNameChar(reader.Peek()))\r
-                       {\r
-                               throw new Exception("a name did not start with a legal character");\r
-                       }\r
-\r
-                       StringBuilder nameBuilder = new StringBuilder();\r
-\r
-                       nameBuilder.Append((char)reader.Read());\r
-\r
-                       while (XmlChar.IsNameChar(reader.Peek()))\r
-                       {\r
-                               nameBuilder.Append((char)reader.Read());\r
-                       }\r
-\r
-                       return nameBuilder.ToString();\r
-               }\r
-\r
-               // Read the next character and compare it against the\r
-               // specified character.\r
-               private void Expect(int expected)\r
-               {\r
-                       int ch = reader.Read();\r
-\r
-                       if (ch != expected)\r
-                       {\r
-                               throw new Exception(String.Format(\r
-                                       "expected '{0}' ({1:X}) but found '{2}' ({3:X})",\r
-                                       (char)expected,\r
-                                       expected,\r
-                                       (char)ch,\r
-                                       ch));\r
-                       }\r
-               }\r
-\r
-               // Does not consume the first non-whitespace character.\r
-               private void SkipWhitespace()\r
-               {\r
-                       while (XmlChar.IsWhitespace(reader.Peek()))\r
-                       {\r
-                               reader.Read();\r
-                       }\r
-               }\r
-       }\r
-}\r
+//
+// System.Xml.XmlTextReader
+//
+// Author:
+//   Jason Diamond (jason@injektilo.org)
+//   Adam Treat (manyoso@yahoo.com)
+//
+// (C) 2001, 2002 Jason Diamond  http://injektilo.org/
+//
+
+// FIXME:
+//   This can only parse basic XML: elements, attributes, processing
+//   instructions, and comments are OK.
+//
+//   It barfs on DOCTYPE declarations.
+//     => No barfing, but parsing is incomplete.
+//        DTD nodes are not still created.
+//
+//   There's also no checking being done for either well-formedness
+//   or validity.
+//
+//   NameTables aren't being used everywhere yet.
+//
+//   Some thought needs to be given to performance. There's too many
+//   strings being allocated.
+//
+//   Some of the MoveTo methods haven't been implemented yet.
+//
+//   LineNumber and LinePosition aren't being tracked.
+//
+//   xml:space, xml:lang, and xml:base aren't being tracked.
+//
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+namespace System.Xml
+{
+       public class XmlTextReader : XmlReader, IXmlLineInfo
+       {
+               WhitespaceHandling whitespaceHandling = WhitespaceHandling.All;
+               #region Constructors
+
+               protected XmlTextReader ()
+               {
+               }
+
+               public XmlTextReader (Stream input)
+                       : this (new StreamReader (input))
+               {
+               }
+
+               public XmlTextReader (string url)
+                       : this(url, new NameTable ())
+               {
+               }
+
+               public XmlTextReader (TextReader input)
+                       : this (input, new NameTable ())
+               {
+               }
+
+               protected XmlTextReader (XmlNameTable nt)
+                       : this (String.Empty, null, XmlNodeType.None, null)
+               {
+               }
+
+               public XmlTextReader (Stream input, XmlNameTable nt)
+                       : this(new StreamReader (input), nt)
+               {
+               }
+
+               public XmlTextReader (string url, Stream input)
+                       : this (url, new StreamReader (input))
+               {
+               }
+
+               public XmlTextReader (string url, TextReader input)
+                       : this (url, input, new NameTable ())
+               {
+               }
+
+               [MonoTODO("Non-filename-url must be supported. Waiting for WebClient")]
+               public XmlTextReader (string url, XmlNameTable nt)
+                       // : this(url, new StreamReader ((Stream)new XmlUrlResolver ().GetEntity (new Uri (url), null, typeof(Stream))), nt)
+                       : this (url, new StreamReader (url), nt)
+               {
+               }
+
+               public XmlTextReader (TextReader input, XmlNameTable nt)
+                       : this(String.Empty, input, nt)
+               {
+               }
+
+               public XmlTextReader (Stream xmlFragment, XmlNodeType fragType, XmlParserContext context)
+                       : this (String.Empty, new StreamReader (xmlFragment), fragType, context)
+               {
+               }
+
+               public XmlTextReader (string url, Stream input, XmlNameTable nt)
+                       : this (url, new StreamReader (input), nt)
+               {
+               }
+
+               public XmlTextReader (string url, TextReader input, XmlNameTable nt)
+                       : this (url, input, XmlNodeType.Document, new XmlParserContext (nt, new XmlNamespaceManager (nt), null, XmlSpace.None))
+               {
+               }
+
+               [MonoTODO("TODO as same as private XmlTextReader(TextReader, XmlNodeType, XmlParserContext)")]
+               public XmlTextReader (string xmlFragment, XmlNodeType fragType, XmlParserContext context)
+                       : this (String.Empty, new StringReader (xmlFragment), fragType, context)
+               {
+               }
+
+               // TODO still remains as described at head of this file,
+               // but it might not be TODO of the constructors...
+               XmlTextReader (string url, TextReader fragment, XmlNodeType fragType, XmlParserContext context)
+               {
+                       this.SetReaderContext(url, context);
+                       this.SetReaderFragment(fragment, fragType);
+               }
+
+               #endregion
+
+               #region Properties
+
+               public override int AttributeCount
+               {
+                       get { return attributes.Count; }
+               }
+
+               public override string BaseURI
+               {
+                       get { return parserContext.BaseURI; }
+               }
+
+               public override int Depth
+               {
+                       get {
+                               return elementDepth;
+                       }
+               }
+
+               public Encoding Encoding
+               {
+                       get { return parserContext.Encoding; }
+               }
+
+               public override bool EOF
+               {
+                       get
+                       {
+                               return
+                                       readState == ReadState.EndOfFile ||
+                                       readState == ReadState.Closed;
+                       }
+               }
+
+               public override bool HasValue
+               {
+                       get { return value != String.Empty;     }
+               }
+
+               public override bool IsDefault
+               {
+                       get
+                       {
+                               // XmlTextReader does not expand default attributes.
+                               return false;
+                       }
+               }
+
+               public override bool IsEmptyElement
+               {
+                       get { return isEmptyElement; }
+               }
+
+               public override string this [int i]
+               {
+                       get { return GetAttribute (i); }
+               }
+
+               public override string this [string name]
+               {
+                       get { return GetAttribute (name); }
+               }
+
+               public override string this [string localName, string namespaceName]
+               {
+                       get { return GetAttribute (localName, namespaceName); }
+               }
+
+               public int LineNumber
+               {
+                       get { return line; }
+               }
+
+               public int LinePosition
+               {
+                       get { return column; }
+               }
+
+               public override string LocalName
+               {
+                       get { return localName; }
+               }
+
+               public override string Name
+               {
+                       get { return name; }
+               }
+
+               [MonoTODO]
+               public bool Namespaces
+               {
+                       get { throw new NotImplementedException (); }
+                       set { throw new NotImplementedException (); }
+               }
+
+               public override string NamespaceURI
+               {
+                       get { return namespaceURI; }
+               }
+
+               public override XmlNameTable NameTable
+               {
+                       get { return parserContext.NameTable; }
+               }
+
+               public override XmlNodeType NodeType
+               {
+                       get { return nodeType; }
+               }
+
+               [MonoTODO]
+               public bool Normalization
+               {
+                       get { throw new NotImplementedException (); }
+                       set { throw new NotImplementedException (); }
+               }
+
+               public override string Prefix
+               {
+                       get { return prefix; }
+               }
+
+               public override char QuoteChar
+               {
+                       get {
+                               // value string holds attribute quotation char.
+                               if (NodeType == XmlNodeType.Attribute)
+                                       return value [0];
+                               else
+                                       return '"';
+                       }
+               }
+
+               public override ReadState ReadState
+               {
+                       get { return readState; }
+               }
+
+               public override string Value
+               {
+                       get {
+                               if(NodeType == XmlNodeType.Attribute)
+                                       return ResolveAttributeValue(value);
+                               else
+                                       return value;
+                       }
+               }
+
+               public WhitespaceHandling WhitespaceHandling
+               {
+                       get { return whitespaceHandling; }
+                       set { whitespaceHandling = value; }
+               }
+
+               [MonoTODO]
+               public override string XmlLang
+               {
+                       get { throw new NotImplementedException (); }
+               }
+
+               [MonoTODO]
+               public XmlResolver XmlResolver
+               {
+                       set { throw new NotImplementedException (); }
+               }
+
+               [MonoTODO]
+               public override XmlSpace XmlSpace
+               {
+                       get { throw new NotImplementedException (); }
+               }
+
+               #endregion
+
+               #region Methods
+
+               [MonoTODO]
+               public override void Close ()
+               {
+                       readState = ReadState.Closed;
+               }
+
+               [MonoTODO]
+               public override string GetAttribute (int i)
+               {
+                       if (i > attributes.Count)
+                               throw new ArgumentOutOfRangeException ("i is smaller than AttributeCount");
+                       else
+                               return ResolveAttributeValue (attributes [orderedAttributes [i]] as string);
+               }
+
+               public override string GetAttribute (string name)
+               {
+                       return attributes.ContainsKey (name) ?
+                               ResolveAttributeValue (attributes [name] as string) : String.Empty;
+               }
+
+               public override string GetAttribute (string localName, string namespaceURI)
+               {
+                       foreach (DictionaryEntry entry in attributes)
+                       {
+                               string thisName = entry.Key as string;
+
+                               int indexOfColon = thisName.IndexOf (':');
+
+                               if (indexOfColon != -1) {
+                                       string thisLocalName = thisName.Substring (indexOfColon + 1);
+
+                                       if (localName == thisLocalName) {
+                                               string thisPrefix = thisName.Substring (0, indexOfColon);
+                                               string thisNamespaceURI = LookupNamespace (thisPrefix);
+
+                                               if (namespaceURI == thisNamespaceURI)
+                                                       return attributes.ContainsKey (thisName) ?
+                                                               ResolveAttributeValue (attributes [thisName] as string) : String.Empty;
+                                       }
+                               } else if (localName == "xmlns" && namespaceURI == "http://www.w3.org/2000/xmlns/" && thisName == "xmlns")
+                                       return attributes.ContainsKey (thisName) ? 
+                                               ResolveAttributeValue (attributes [thisName] as string) : String.Empty;
+                       }
+
+                       return String.Empty;
+               }
+
+               [MonoTODO]
+               public TextReader GetRemainder ()
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoTODO]
+               bool IXmlLineInfo.HasLineInfo ()
+               {
+                       return false;
+               }
+
+               public override string LookupNamespace (string prefix)
+               {
+                       return parserContext.NamespaceManager.LookupNamespace (prefix);
+               }
+
+               public override void MoveToAttribute (int i)
+               {
+                       MoveToElement ();
+
+                       if (attributes == null || orderedAttributes.Count < i || i < 0)
+                               throw new ArgumentOutOfRangeException ("attribute index out of range.");
+
+                       string name = orderedAttributes [i] as string;
+                       string value = attributes [name] as string;
+                       SetProperties (
+                               XmlNodeType.Attribute, // nodeType
+                               name, // name
+                               false, // isEmptyElement
+                               value, // value
+                               false // clearAttributes
+                               );
+               }
+
+               public override bool MoveToAttribute (string name)
+               {
+                       MoveToElement ();
+                       bool match = false;
+
+                       if (attributes == null)
+                               return false;
+
+                       if (orderedAttributesEnumerator == null) {
+                               SaveProperties ();
+                               orderedAttributesEnumerator = orderedAttributes.GetEnumerator ();
+                       }
+
+                       while (orderedAttributesEnumerator.MoveNext ()) {
+                               if(name == orderedAttributesEnumerator.Current as string) {
+                                       match = true;
+                                       break;
+                               }
+                       }
+
+                       if (match) {
+                               string value = attributes [name] as string;
+                               SetProperties (
+                                       XmlNodeType.Attribute, // nodeType
+                                       name, // name
+                                       false, // isEmptyElement
+                                       value, // value
+                                       false // clearAttributes
+                               );
+                       }
+
+                       return match;
+               }
+
+               [MonoTODO]
+               public override bool MoveToAttribute (string localName, string namespaceName)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public override bool MoveToElement ()
+               {
+                       if (orderedAttributesEnumerator != null) {
+                               orderedAttributesEnumerator = null;
+                               RestoreProperties ();
+                               return true;
+                       }
+
+                       return false;
+               }
+
+               public override bool MoveToFirstAttribute ()
+               {
+                       MoveToElement ();
+                       return MoveToNextAttribute ();
+               }
+
+               public override bool MoveToNextAttribute ()
+               {
+                       if (attributes == null)
+                               return false;
+
+                       if (orderedAttributesEnumerator == null) {
+                               SaveProperties ();
+                               orderedAttributesEnumerator = orderedAttributes.GetEnumerator ();
+                       }
+
+                       if (orderedAttributesEnumerator.MoveNext ()) {
+                               string name = orderedAttributesEnumerator.Current as string;
+                               string value = attributes [name] as string;
+                               SetProperties (
+                                       XmlNodeType.Attribute, // nodeType
+                                       name, // name
+                                       false, // isEmptyElement
+                                       value, // value
+                                       false // clearAttributes
+                               );
+                               return true;
+                       }
+
+                       return false;
+               }
+
+               public override bool Read ()
+               {
+                       bool more = false;
+
+                       readState = ReadState.Interactive;
+
+                       more = ReadContent ();
+
+                       return more;
+               }
+
+               [MonoTODO("This method should consider entity references")]
+               public override bool ReadAttributeValue ()
+               {
+                       // reading attribute value phase now stopped
+                       if(attributeStringCurrentPosition < 0 ||
+                                       attributeString.Length < attributeStringCurrentPosition) {
+                               attributeStringCurrentPosition = 0;
+                               attributeString = String.Empty;
+                               return false;
+                       }
+
+                       // If not started, then initialize attributeString when parsing is at start.
+                       if(attributeStringCurrentPosition == 0)
+                               attributeString =
+                                       value.Substring (1, value.Length - 2);
+
+                       bool returnEntity = false;
+                       value = String.Empty;
+                       int nextPosition = attributeString.IndexOf ('&',
+                               attributeStringCurrentPosition);
+
+                       // if attribute string starts from '&' then it may be (unparsable) entity reference.
+                       if(nextPosition == 0) {
+                               string parsed = ReadAttributeValueEntityReference ();
+                               if(parsed == null) {
+                                       // return entity (It is only this case to return entity reference.)
+                                       int endEntityPosition = attributeString.IndexOf (';',
+                                               attributeStringCurrentPosition);
+                                       SetProperties (XmlNodeType.EntityReference,
+                                               attributeString.Substring (attributeStringCurrentPosition + 1,
+                                               endEntityPosition - attributeStringCurrentPosition - 1),
+                                               false,
+                                               String.Empty,
+                                               false);
+                                       attributeStringCurrentPosition = endEntityPosition + 1;
+
+                                       return true;
+                               }
+                               else
+                                       value += parsed;
+                       }
+
+                       // Other case always set text node.
+                       while(!returnEntity) {
+                               nextPosition = attributeString.IndexOf ('&', attributeStringCurrentPosition);
+                               if(nextPosition < 0) {
+                                       // Reached to the end of value string.
+                                       value += attributeString.Substring (attributeStringCurrentPosition);
+                                       attributeStringCurrentPosition = -1;
+                                       break;
+                               } else if(nextPosition == attributeStringCurrentPosition) {
+                                       string parsed = ReadAttributeValueEntityReference ();
+                                       if(parsed != null)
+                                               value += parsed;
+                                       else {
+                                               // Found that an entity reference starts from this point.
+                                               // Then once stop to parse attribute value and then return text.
+                                               value += attributeString.Substring (attributeStringCurrentPosition,
+                                                       nextPosition - attributeStringCurrentPosition);
+                                               break;
+                                       }
+                               } else {
+                                       value += attributeString.Substring (attributeStringCurrentPosition,
+                                               nextPosition - attributeStringCurrentPosition);
+                                       attributeStringCurrentPosition = nextPosition;
+                                       continue;
+                               }
+                       }
+
+                       SetProperties(XmlNodeType.Text,
+                               "#text",
+                               false,
+                               value,
+                               false);
+
+                       return true;
+               }
+
+               [MonoTODO]
+               public int ReadBase64 (byte [] buffer, int offset, int length)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoTODO]
+               public int ReadBinHex (byte [] buffer, int offset, int length)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoTODO]
+               public int ReadChars (char [] buffer, int offset, int length)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoTODO]
+               public override string ReadInnerXml ()
+               {
+                       // Still need a Well Formedness check.
+                       // Will wait for Validating reader ;-)
+                       if (NodeType == XmlNodeType.Attribute) {
+                               return Value;
+                       } else {
+                               saveToXmlBuffer = true;
+                               string startname = this.Name;
+                               string endname = string.Empty;
+                               readState = ReadState.Interactive;
+
+                               while (startname != endname) {
+                                       ReadContent ();
+                                       endname = this.Name;
+                               }
+
+                               xmlBuffer.Replace (currentTag.ToString (), "");
+                               saveToXmlBuffer = false;
+                               string InnerXml = xmlBuffer.ToString ();
+                               xmlBuffer.Length = 0;
+                               return InnerXml;
+                       }
+               }
+
+               [MonoTODO]
+               public override string ReadOuterXml ()
+               {
+                       if (NodeType == XmlNodeType.Attribute) {
+                               return Name + "=\"" + Value.Replace ("\"", "&quot;") + "\"";
+                       } else {
+                               saveToXmlBuffer = true;
+                               xmlBuffer.Append (currentTag.ToString ());
+                               int startDepth = Depth;
+                               readState = ReadState.Interactive;
+
+                               do {
+                                       ReadContent ();
+                               } while (Depth > startDepth);
+
+                               saveToXmlBuffer = false;
+                               string OuterXml = xmlBuffer.ToString ();
+                               xmlBuffer.Length = 0;
+                               return OuterXml;
+                       }
+               }
+
+               [MonoTODO]
+               public override string ReadString ()
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoTODO]
+               public void ResetState ()
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public override void ResolveEntity ()
+               {
+                       // XmlTextReaders don't resolve entities.
+                       throw new InvalidOperationException ("XmlTextReader cannot resolve external entities.");
+               }
+
+               #endregion
+
+               #region Internals
+               internal string publicId;
+               internal string systemId;
+
+               internal void SetReaderContext (string url, XmlParserContext context)
+               {
+                       parserContext = context;
+                       parserContext.BaseURI = url;
+                       Init ();
+               }
+
+               internal void SetReaderFragment(TextReader fragment, XmlNodeType fragType)
+               {
+                       this.reader = fragment;
+                       can_seek = fragment != null && fragment.Peek () != -1;
+
+                       if (fragType == XmlNodeType.Attribute)
+                               value = "''";
+/*     for future use
+                       switch(fragType)
+                       {
+                       case XmlNodeType.Attribute:     // attribute content
+                               parserContext.InputState = XmlParserInputState.AttributeValue;
+                               break;
+                       case XmlNodeType.DocumentFragment:      // element content
+                               parserContext.InputState = XmlParserInputState.Content;
+                               break;
+                       case XmlNodeType.Element:       // one element
+                               parserContext.InputState = XmlParserInputState.StartTag;
+                               break;
+                       case XmlNodeType.Document:      // document content
+                               parserContext.InputState = XmlParserInputState.Start;
+                               break;
+                       default:
+                               throw new InvalidOperationException("setting this xml node type not allowed.");
+                       }
+*/
+               }
+               #endregion
+
+               #region Privates
+
+               private XmlParserContext parserContext;
+
+               private TextReader reader;
+               private ReadState readState;
+
+               private int depth;
+               private int elementDepth;
+               private bool depthDown;
+
+               private bool popScope;
+
+               private XmlNodeType nodeType;
+               private string name;
+               private string prefix;
+               private string localName;
+               private string namespaceURI;
+               private bool isEmptyElement;
+               private string value;
+
+               private XmlNodeType saveNodeType;
+               private string saveName;
+               private string savePrefix;
+               private string saveLocalName;
+               private string saveNamespaceURI;
+               private bool saveIsEmptyElement;
+
+               private Hashtable attributes;
+               private ArrayList orderedAttributes;
+               private IEnumerator orderedAttributesEnumerator;
+
+               private bool returnEntityReference;
+               private string entityReferenceName;
+
+               private char [] nameBuffer;
+               private int nameLength;
+               private int nameCapacity;
+               private const int initialNameCapacity = 256;
+
+               private char [] valueBuffer;
+               private int valueLength;
+               private int valueCapacity;
+               private const int initialValueCapacity = 8192;
+
+               private StringBuilder xmlBuffer; // This is for Read(Inner|Outer)Xml
+               private StringBuilder currentTag; // A buffer for ReadContent for ReadOuterXml
+               private bool saveToXmlBuffer;
+               private int line = 1;
+               private int column = 1;
+               private bool has_peek;
+               private bool can_seek;
+               private int peek_char;
+
+               private string attributeString = String.Empty;
+               private int attributeStringCurrentPosition;
+
+               private void Init ()
+               {
+                       readState = ReadState.Initial;
+
+                       depth = 0;
+                       depthDown = false;
+
+                       popScope = false;
+
+                       nodeType = XmlNodeType.None;
+                       name = String.Empty;
+                       prefix = String.Empty;
+                       localName = string.Empty;
+                       isEmptyElement = false;
+                       value = String.Empty;
+
+                       attributes = new Hashtable ();
+                       orderedAttributes = new ArrayList ();
+                       orderedAttributesEnumerator = null;
+
+                       returnEntityReference = false;
+                       entityReferenceName = String.Empty;
+
+                       nameBuffer = new char [initialNameCapacity];
+                       nameLength = 0;
+                       nameCapacity = initialNameCapacity;
+
+                       valueBuffer = new char [initialValueCapacity];
+                       valueLength = 0;
+                       valueCapacity = initialValueCapacity;
+
+                       xmlBuffer = new StringBuilder ();
+                       currentTag = new StringBuilder ();
+               }
+
+               // Use this method rather than setting the properties
+               // directly so that all the necessary properties can
+               // be changed in harmony with each other. Maybe the
+               // fields should be in a seperate class to help enforce
+               // this.
+               private void SetProperties (
+                       XmlNodeType nodeType,
+                       string name,
+                       bool isEmptyElement,
+                       string value,
+                       bool clearAttributes)
+               {
+                       this.nodeType = nodeType;
+                       this.name = name;
+                       this.isEmptyElement = isEmptyElement;
+                       this.value = value;
+                       this.elementDepth = depth;
+
+                       if (clearAttributes)
+                               ClearAttributes ();
+
+                       int indexOfColon = name.IndexOf (':');
+
+                       if (indexOfColon == -1) {
+                               prefix = String.Empty;
+                               localName = name;
+                       } else {
+                               prefix = name.Substring (0, indexOfColon);
+                               localName = name.Substring (indexOfColon + 1);
+                       }
+
+                       namespaceURI = LookupNamespace (prefix);
+               }
+
+               private void SaveProperties ()
+               {
+                       saveNodeType = nodeType;
+                       saveName = name;
+                       savePrefix = prefix;
+                       saveLocalName = localName;
+                       saveNamespaceURI = namespaceURI;
+                       saveIsEmptyElement = isEmptyElement;
+                       // An element's value is always String.Empty.
+               }
+
+               private void RestoreProperties ()
+               {
+                       nodeType = saveNodeType;
+                       name = saveName;
+                       prefix = savePrefix;
+                       localName = saveLocalName;
+                       namespaceURI = saveNamespaceURI;
+                       isEmptyElement = saveIsEmptyElement;
+                       value = String.Empty;
+               }
+
+               private void AddAttribute (string name, string value)
+               {
+                       attributes.Add (name, value);
+                       orderedAttributes.Add (name);
+               }
+
+               private void ClearAttributes ()
+               {
+                       if (attributes.Count > 0) {
+                               attributes.Clear ();
+                               orderedAttributes.Clear ();
+                       }
+
+                       orderedAttributesEnumerator = null;
+               }
+
+               private int PeekChar ()
+               {
+                       if (can_seek)
+                               return reader.Peek ();
+
+                       if (has_peek)
+                               return peek_char;
+
+                       peek_char = reader.Read ();
+                       has_peek = true;
+                       return peek_char;
+               }
+
+               private int ReadChar ()
+               {
+                       int ch;
+                       if (has_peek) {
+                               ch = peek_char;
+                               has_peek = false;
+                       } else {
+                               ch = reader.Read ();
+                       }
+
+                       if (ch == '\n') {
+                               line++;
+                               column = 1;
+                       } else {
+                               column++;
+                       }
+                       if (saveToXmlBuffer) {
+                               xmlBuffer.Append ((char) ch);
+                       }
+                       currentTag.Append ((char) ch);
+                       return ch;
+               }
+
+               // This should really keep track of some state so
+               // that it's not possible to have more than one document
+               // element or text outside of the document element.
+               private bool ReadContent ()
+               {
+                       currentTag.Length = 0;
+                       if (popScope) {
+                               parserContext.NamespaceManager.PopScope ();
+                               popScope = false;
+                       }
+
+                       if (returnEntityReference) {
+                               SetEntityReferenceProperties ();
+                       } else {
+                       switch (PeekChar ())
+                               {
+                               case '<':
+                                       ReadChar ();
+                                       ReadTag ();
+                                       break;
+                               case '\r':
+                                       if (whitespaceHandling == WhitespaceHandling.All ||
+                                           whitespaceHandling == WhitespaceHandling.Significant)
+                                               return ReadWhitespace ();
+
+                                       ReadChar ();
+                                       return ReadContent ();
+                               case '\n':
+                                       if (whitespaceHandling == WhitespaceHandling.All ||
+                                           whitespaceHandling == WhitespaceHandling.Significant)
+                                               return ReadWhitespace ();
+
+                                       ReadChar ();
+                                       return ReadContent ();
+                               case ' ':
+                                       if (whitespaceHandling == WhitespaceHandling.All ||
+                                           whitespaceHandling == WhitespaceHandling.Significant)
+                                               return ReadWhitespace ();
+
+                                       SkipWhitespace ();
+                                       return ReadContent ();
+                               case -1:
+                                       readState = ReadState.EndOfFile;
+                                       SetProperties (
+                                               XmlNodeType.None, // nodeType
+                                               String.Empty, // name
+                                               false, // isEmptyElement
+                                               String.Empty, // value
+                                               true // clearAttributes
+                                       );
+                                       break;
+                               default:
+                                       ReadText (true);
+                                       break;
+                               }
+                       }
+                       return this.ReadState != ReadState.EndOfFile;
+               }
+
+               private void SetEntityReferenceProperties ()
+               {
+                       SetProperties (
+                               XmlNodeType.EntityReference, // nodeType
+                               entityReferenceName, // name
+                               false, // isEmptyElement
+                               String.Empty, // value
+                               true // clearAttributes
+                       );
+
+                       returnEntityReference = false;
+                       entityReferenceName = String.Empty;
+               }
+
+               // The leading '<' has already been consumed.
+               private void ReadTag ()
+               {
+                       switch (PeekChar ())
+                       {
+                       case '/':
+                               ReadChar ();
+                               ReadEndTag ();
+                               break;
+                       case '?':
+                               ReadChar ();
+                               ReadProcessingInstruction ();
+                               break;
+                       case '!':
+                               ReadChar ();
+                               ReadDeclaration ();
+                               break;
+                       default:
+                               ReadStartTag ();
+                               break;
+                       }
+               }
+
+               // The leading '<' has already been consumed.
+               private void ReadStartTag ()
+               {
+                       parserContext.NamespaceManager.PushScope ();
+
+                       string name = ReadName ();
+                       SkipWhitespace ();
+
+                       bool isEmptyElement = false;
+
+                       ClearAttributes ();
+
+                       if (XmlChar.IsFirstNameChar (PeekChar ()))
+                               ReadAttributes ();
+
+                       if (PeekChar () == '/') {
+                               ReadChar ();
+                               isEmptyElement = true;
+                               depthDown = true;
+                               popScope = true;
+                       }
+
+                       Expect ('>');
+
+                       SetProperties (
+                               XmlNodeType.Element, // nodeType
+                               name, // name
+                               isEmptyElement, // isEmptyElement
+                               String.Empty, // value
+                               false // clearAttributes
+                       );
+
+                       if (!depthDown)
+                               ++depth;
+                       else
+                               depthDown = false;
+
+               }
+
+               // The reader is positioned on the first character
+               // of the element's name.
+               private void ReadEndTag ()
+               {
+                       string name = ReadName ();
+                       SkipWhitespace ();
+                       Expect ('>');
+
+                       --depth;
+
+                       SetProperties (
+                               XmlNodeType.EndElement, // nodeType
+                               name, // name
+                               false, // isEmptyElement
+                               String.Empty, // value
+                               true // clearAttributes
+                       );
+
+                       popScope = true;
+               }
+
+               private void AppendNameChar (int ch)
+               {
+                       CheckNameCapacity ();
+                       nameBuffer [nameLength++] = (char)ch;
+               }
+
+               private void CheckNameCapacity ()
+               {
+                       if (nameLength == nameCapacity) {
+                               nameCapacity = nameCapacity * 2;
+                               char [] oldNameBuffer = nameBuffer;
+                               nameBuffer = new char [nameCapacity];
+                               Array.Copy (oldNameBuffer, nameBuffer, nameLength);
+                       }
+               }
+
+               private string CreateNameString ()
+               {
+                       return new String (nameBuffer, 0, nameLength);
+               }
+
+               private void AppendValueChar (int ch)
+               {
+                       CheckValueCapacity ();
+                       valueBuffer [valueLength++] = (char)ch;
+               }
+
+               private void CheckValueCapacity ()
+               {
+                       if (valueLength == valueCapacity) {
+                               valueCapacity = valueCapacity * 2;
+                               char [] oldValueBuffer = valueBuffer;
+                               valueBuffer = new char [valueCapacity];
+                               Array.Copy (oldValueBuffer, valueBuffer, valueLength);
+                       }
+               }
+
+               private string CreateValueString ()
+               {
+                       return new String (valueBuffer, 0, valueLength);
+               }
+
+               // The reader is positioned on the first character
+               // of the text.
+               private void ReadText (bool cleanValue)
+               {
+                       if (cleanValue)
+                               valueLength = 0;
+
+                       int ch = PeekChar ();
+
+                       while (ch != '<' && ch != -1) {
+                               if (ch == '&') {
+                                       ReadChar ();
+                                       if (ReadReference (false))
+                                               break;
+                               } else
+                                       AppendValueChar (ReadChar ());
+
+                               ch = PeekChar ();
+                       }
+
+                       if (returnEntityReference && valueLength == 0) {
+                               SetEntityReferenceProperties ();
+                       } else {
+                               SetProperties (
+                                       XmlNodeType.Text, // nodeType
+                                       String.Empty, // name
+                                       false, // isEmptyElement
+                                       CreateValueString (), // value
+                                       true // clearAttributes
+                               );
+                       }
+               }
+
+               // The leading '&' has already been consumed.
+               // Returns true if the entity reference isn't a simple
+               // 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)
+               {
+                       if (PeekChar () == '#') {
+                               ReadChar ();
+                               ReadCharacterReference ();
+                       } else
+                               ReadEntityReference (ignoreEntityReferences);
+
+                       return returnEntityReference;
+               }
+
+               private void ReadCharacterReference ()
+               {
+                       int value = 0;
+
+                       if (PeekChar () == 'x') {
+                               ReadChar ();
+
+                               while (PeekChar () != ';' && PeekChar () != -1) {
+                                       int ch = ReadChar ();
+
+                                       if (ch >= '0' && ch <= '9')
+                                               value = (value << 4) + ch - '0';
+                                       else if (ch >= 'A' && ch <= 'F')
+                                               value = (value << 4) + ch - 'A' + 10;
+                                       else if (ch >= 'a' && ch <= 'f')
+                                               value = (value << 4) + ch - 'a' + 10;
+                                       else
+                                               throw new XmlException (
+                                                       String.Format (
+                                                               "invalid hexadecimal digit: {0} (#x{1:X})",
+                                                               (char)ch,
+                                                               ch));
+                               }
+                       } else {
+                               while (PeekChar () != ';' && PeekChar () != -1) {
+                                       int ch = ReadChar ();
+
+                                       if (ch >= '0' && ch <= '9')
+                                               value = value * 10 + ch - '0';
+                                       else
+                                               throw new XmlException (
+                                                       String.Format (
+                                                               "invalid decimal digit: {0} (#x{1:X})",
+                                                               (char)ch,
+                                                               ch));
+                               }
+                       }
+
+                       ReadChar (); // ';'
+
+                       AppendValueChar (value);
+               }
+
+               private void ReadEntityReference (bool ignoreEntityReferences)
+               {
+                       nameLength = 0;
+
+                       int ch = PeekChar ();
+
+                       while (ch != ';' && ch != -1) {
+                               AppendNameChar (ReadChar ());
+                               ch = PeekChar ();
+                       }
+
+                       Expect (';');
+
+                       string name = CreateNameString ();
+
+                       switch (name)
+                       {
+                               case "lt":
+                                       AppendValueChar ('<');
+                                       break;
+                               case "gt":
+                                       AppendValueChar ('>');
+                                       break;
+                               case "amp":
+                                       AppendValueChar ('&');
+                                       break;
+                               case "apos":
+                                       AppendValueChar ('\'');
+                                       break;
+                               case "quot":
+                                       AppendValueChar ('"');
+                                       break;
+                               default:
+                                       if (ignoreEntityReferences) {
+                                               AppendValueChar ('&');
+
+                                               foreach (char ch2 in name) {
+                                                       AppendValueChar (ch2);
+                                               }
+
+                                               AppendValueChar (';');
+                                       } else {
+                                               returnEntityReference = true;
+                                               entityReferenceName = name;
+                                       }
+                                       break;
+                       }
+               }
+
+               // The reader is positioned on the first character of
+               // the attribute name.
+               private void ReadAttributes ()
+               {
+                       do {
+                               string name = ReadName ();
+                               SkipWhitespace ();
+                               Expect ('=');
+                               SkipWhitespace ();
+                               string value = ReadAttribute ();
+                               SkipWhitespace ();
+
+                               if (name == "xmlns")
+                                       parserContext.NamespaceManager.AddNamespace (String.Empty, ResolveAttributeValue (value));
+                               else if (name.StartsWith ("xmlns:"))
+                                       parserContext.NamespaceManager.AddNamespace (name.Substring (6), ResolveAttributeValue (value));
+
+                               AddAttribute (name, value);
+                       } while (PeekChar () != '/' && PeekChar () != '>' && PeekChar () != -1);
+               }
+
+               // The reader is positioned on the quote character.
+               private string ReadAttribute ()
+               {
+                       valueLength = 0;
+
+                       int quoteChar = ReadChar ();
+
+                       if (quoteChar != '\'' && quoteChar != '\"')
+                               throw new XmlException ("an attribute value was not quoted");
+
+                       // this keeps quote char to get QuoteChar property correctly.
+                       AppendValueChar (quoteChar);
+
+                       while (PeekChar () != quoteChar) {
+                               int ch = ReadChar ();
+
+                               switch (ch)
+                               {
+                               case '<':
+                                       throw new XmlException ("attribute values cannot contain '<'");
+// expansion of entity now should be done at ResolveAttributeValue() method
+//                             case '&':
+//                                     ReadReference (true);
+//                                     break;
+                               case -1:
+                                       throw new XmlException ("unexpected end of file in an attribute value");
+                               default:
+                                       AppendValueChar (ch);
+                                       break;
+                               }
+                       }
+
+                       ReadChar (); // quoteChar
+                       AppendValueChar (quoteChar);
+
+                       return CreateValueString ();
+               }
+
+               // The reader is positioned on the first character
+               // of the target.
+               //
+               // Now it also reads XmlDeclaration, this method name became improper...
+               private void ReadProcessingInstruction ()
+               {
+                       string target = ReadName ();
+                       SkipWhitespace ();
+
+                       valueLength = 0;
+
+                       while (PeekChar () != -1) {
+                               int ch = ReadChar ();
+
+                               if (ch == '?' && PeekChar () == '>') {
+                                       ReadChar ();
+                                       break;
+                               }
+
+                               AppendValueChar ((char)ch);
+                       }
+
+/* for future use
+                       if(target == "xml") && parserContext.InputState != XmlParserInputState.Start)
+                               throw new XmlException("Xml declaration is not allowed here.");
+                       else {
+                               parserContext.InputState = XmlParserInputState.DTD; //for future use
+                       }
+*/
+                       SetProperties (
+                               target == "xml" ?
+                               XmlNodeType.XmlDeclaration :
+                               XmlNodeType.ProcessingInstruction, // nodeType
+                               target, // name
+                               false, // isEmptyElement
+                               CreateValueString (), // value
+                               true // 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;
+                       }
+               }
+
+               // The reader is positioned on the first character after
+               // the leading '<!--'.
+               private void ReadComment ()
+               {
+                       valueLength = 0;
+
+                       while (PeekChar () != -1) {
+                               int ch = ReadChar ();
+
+                               if (ch == '-' && PeekChar () == '-') {
+                                       ReadChar ();
+
+                                       if (PeekChar () != '>')
+                                               throw new XmlException ("comments cannot contain '--'");
+
+                                       ReadChar ();
+                                       break;
+                               }
+
+                               AppendValueChar ((char)ch);
+                       }
+
+                       SetProperties (
+                               XmlNodeType.Comment, // nodeType
+                               String.Empty, // name
+                               false, // isEmptyElement
+                               CreateValueString (), // value
+                               true // clearAttributes
+                       );
+               }
+
+               // The reader is positioned on the first character after
+               // the leading '<![CDATA['.
+               private void ReadCDATA ()
+               {
+                       valueLength = 0;
+
+                       while (PeekChar () != -1) {
+                               int ch = ReadChar ();
+
+                               if (ch == ']' && PeekChar () == ']') {
+                                       ch = ReadChar (); // ']'
+
+                                       if (PeekChar () == '>') {
+                                               ReadChar (); // '>'
+                                               break;
+                                       } else {
+                                               AppendValueChar (']');
+                                               AppendValueChar (']');
+                                               ch = ReadChar ();
+                                       }
+                               }
+
+                               AppendValueChar ((char)ch);
+                       }
+
+                       SetProperties (
+                               XmlNodeType.CDATA, // nodeType
+                               String.Empty, // name
+                               false, // isEmptyElement
+                               CreateValueString (), // value
+                               true // clearAttributes
+                       );
+               }
+
+               // The reader is positioned on the first character after
+               // the leading '<!DOCTYPE'.
+               private void ReadDoctypeDecl ()
+               {
+                       string doctypeName = null;
+                       string publicId = String.Empty;
+                       string systemId = String.Empty;
+
+                       SkipWhitespace ();
+                       doctypeName = ReadName ();
+                       SkipWhitespace ();
+                       xmlBuffer.Length = 0;
+                       switch(PeekChar ())
+                       {
+                       case 'S':
+                               systemId = ReadSystemLiteral (true);
+                               break;
+                       case 'P':
+                               publicId = ReadPubidLiteral ();
+                               SkipWhitespace ();
+                               systemId = ReadSystemLiteral (false);
+                               break;
+                       }
+                       SkipWhitespace ();
+
+
+                       if(PeekChar () == '[')
+                       {
+                               // read markupdecl etc. or end of decl
+                               ReadChar ();
+                               xmlBuffer.Length = 0;
+                               saveToXmlBuffer = true;
+                               do {
+                                       ReadDTDInternalSubset ();
+                               } while(nodeType != XmlNodeType.None);
+                               xmlBuffer.Remove (xmlBuffer.Length - 1, 1);     // cut off ']'
+                               saveToXmlBuffer = false;
+                       }
+                       // end of DOCTYPE decl.
+                       SkipWhitespace ();
+                       Expect ('>');
+
+                       parserContext.InternalSubset = xmlBuffer.ToString ();
+
+                       // set properties for <!DOCTYPE> node
+                       SetProperties (
+                               XmlNodeType.DocumentType, // nodeType
+                               doctypeName, // name
+                               false, // isEmptyElement
+                               parserContext.InternalSubset, // value
+                               true // clearAttributes
+                               );
+               }
+
+               // Read any one of following:
+               //   elementdecl, AttlistDecl, EntityDecl, NotationDecl,
+               //   PI, Comment, Parameter Entity, or doctype termination char(']')
+               //
+               // returns a node of some nodeType or null, setting nodeType.
+               //       (if None then ']' was found.)
+               private void ReadDTDInternalSubset()
+               {
+                       SkipWhitespace ();
+                       switch(ReadChar ())
+                       {
+                       case ']':
+                               nodeType = XmlNodeType.None;
+                               break;
+                       case '%':
+                               string peName = ReadName ();
+                               Expect (';');
+                               nodeType = XmlNodeType.EntityReference; // It's chating a bit;-)
+                               break;
+                       case '<':
+                               switch(ReadChar ())
+                               {
+                               case '?':
+                                       ReadProcessingInstruction ();
+                                       break;
+                               case '!':
+                                       switch(ReadChar ())
+                                       {
+                                       case '-':
+                                               Expect ('-');
+                                               ReadComment ();
+                                               break;
+                                       case 'E':
+                                               switch(ReadChar ())
+                                               {
+                                               case 'N':
+                                                       Expect ("TITY");
+                                                       ReadEntityDecl ();
+                                                       break;
+                                               case 'L':
+                                                       Expect ("EMENT");
+                                                       ReadElementDecl ();
+                                                       break;
+                                               default:
+                                                       throw new XmlException ("Syntax Error after '<!E' (ELEMENT or ENTITY must be found)");
+                                               }
+                                               break;
+                                       case 'A':
+                                               Expect ("TTLIST");
+                                               ReadAttListDecl ();
+                                               break;
+                                       case 'N':
+                                               Expect ("OTATION");
+                                               ReadNotationDecl ();
+                                               break;
+                                       default:
+                                               throw new XmlException ("Syntax Error after '<!' characters.");
+                                       }
+                                       break;
+                               default:
+                                       throw new XmlException ("Syntax Error after '<' character.");
+                               }
+                               break;
+                       default:
+                               throw new XmlException ("Syntax Error inside doctypedecl markup.");
+                       }
+               }
+
+               // The reader is positioned on the head of the name.
+               private void ReadElementDecl()
+               {
+                       while(ReadChar () != '>');
+               }
+
+               private void ReadEntityDecl()
+               {
+                       while(ReadChar () != '>');
+               }
+
+               private void ReadAttListDecl()
+               {
+                       while(ReadChar () != '>');
+               }
+
+               private void ReadNotationDecl()
+               {
+                       while(ReadChar () != '>');
+               }
+               
+               // The reader is positioned on the first 'S' of "SYSTEM".
+               private string ReadSystemLiteral (bool expectSYSTEM)
+               {
+                       if(expectSYSTEM)
+                               Expect ("SYSTEM");
+                       SkipWhitespace ();
+                       int quoteChar = ReadChar ();    // apos or quot
+                       xmlBuffer.Length = 0;
+                       saveToXmlBuffer = true;
+                       int c = 0;
+                       while(c != quoteChar) {
+                               c = ReadChar ();
+                               if(c < 0) throw new XmlException ("Unexpected end of stream in ExternalID.");
+                       }
+                       saveToXmlBuffer = false;
+                       xmlBuffer.Remove (xmlBuffer.Length-1, 1);       // cut quoteChar
+                       return xmlBuffer.ToString ();
+               }
+
+               private string ReadPubidLiteral()
+               {
+                       Expect ("PUBLIC");
+                       SkipWhitespace ();
+                       int quoteChar = ReadChar ();
+                       xmlBuffer.Length = 0;
+                       saveToXmlBuffer = true;
+                       int c = 0;
+                       while(c != quoteChar)
+                       {
+                               c = ReadChar ();
+                               if(c < 0) throw new XmlException ("Unexpected end of stream in ExternalID.");
+                               if(c != quoteChar && !XmlChar.IsPubidChar (c))
+                                       throw new XmlException("character '" + (char)c + "' not allowed for PUBLIC ID");
+                       }
+                       ReadChar();     // skips quoteChar
+                       xmlBuffer.Remove (xmlBuffer.Length-1, 1);       // cut quoteChar
+                       saveToXmlBuffer = false;
+                       return xmlBuffer.ToString ();
+               }
+
+               // The reader is positioned on the first character
+               // of the name.
+               private string ReadName ()
+               {
+                       if (!XmlChar.IsFirstNameChar (PeekChar ()))
+                               throw new XmlException ("a name did not start with a legal character");
+
+                       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 (
+                                       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 void SkipWhitespace ()
+               {
+                       //FIXME: Should not skip if whitespaceHandling == WhiteSpaceHandling.None
+                       while (XmlChar.IsWhitespace (PeekChar ()))
+                               ReadChar ();
+               }
+
+               private bool ReadWhitespace ()
+               {
+                       valueLength = 0;
+                       int ch = PeekChar ();
+                       do {
+                               AppendValueChar (ReadChar ());
+                       } while ((ch = PeekChar ()) != -1 && XmlChar.IsWhitespace (ch));
+
+                       if (ch != -1 && ch != '<')
+                               ReadText (false);
+                       else
+                               SetProperties (XmlNodeType.Whitespace,
+                                              String.Empty,
+                                              false,
+                                              CreateValueString (),
+                                              true);
+
+                       return (PeekChar () != -1);
+               }
+
+               // read entity reference from attribute string and if parsable then return the value.
+               private string ReadAttributeValueEntityReference ()
+               {
+                       int endEntityPosition = attributeString.IndexOf(';',
+                               attributeStringCurrentPosition);
+                       string entityName = attributeString.Substring (attributeStringCurrentPosition + 1,
+                               endEntityPosition - attributeStringCurrentPosition - 1);
+
+                       attributeStringCurrentPosition = endEntityPosition + 1;
+
+                       if(entityName [0] == '#') {
+                               char c;
+                               // character entity
+                               if(entityName [1] == 'x') {
+                                       // hexadecimal
+                                       c = (char) int.Parse ("0" + entityName.Substring (2),
+                                               System.Globalization.NumberStyles.HexNumber);
+                               } else {
+                                       // decimal
+                                       c = (char) int.Parse (entityName.Substring (1));
+                               }
+                               return c.ToString();
+                       }
+                       else {
+                               switch(entityName)
+                               {
+                               case "lt": return "<";
+                               case "gt": return ">";
+                               case "amp": return "&";
+                               case "quot": return "\"";
+                               case "apos": return "'";
+                               default: return null;
+                               }
+                       }
+               }
+
+               private string ResolveAttributeValue (string unresolved)
+               {
+                       if(unresolved == null) return null;
+                       StringBuilder resolved = new StringBuilder();
+                       int pos = 0;
+
+                       // trim start/end edge of quotation character.
+                       unresolved = unresolved.Substring (1, unresolved.Length - 2);
+
+                       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 {
+                                       switch(entityName) {
+                                       case "lt": resolved.Append ("<"); break;
+                                       case "gt": resolved.Append (">"); break;
+                                       case "amp": resolved.Append ("&"); break;
+                                       case "quot": resolved.Append ("\""); break;
+                                       case "apos": resolved.Append ("'"); break;
+                                       // With respect to "Value", MS document is helpless
+                                       // and the implemention returns inconsistent value
+                                       // (e.g. XML: "&ent; &amp;ent;" ---> Value: "&ent; &ent;".)
+                                       default: resolved.Append ("&" + entityName + ";"); break;
+                                       }
+                               }
+                               pos = endPos + 1;
+                               if(pos > unresolved.Length)
+                                       break;
+                               next = unresolved.IndexOf('&', pos);
+                       }
+                       resolved.Append (unresolved.Substring(pos));
+
+                       return resolved.ToString();
+               }
+
+               #endregion
+       }
+}