2002-11-24 Duncan Mak <duncan@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlReader.cs
index e386b8195937290aa9398303ce4be80c76d16e6f..6e4d243b2f659a21fbeb409f8407170c4ada6d27 100644 (file)
-// -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-\r
-//\r
-// System.Xml.XmlReader.cs\r
-//\r
-// Author:\r
-//   Jason Diamond (jason@injektilo.org)\r
-//\r
-// (C) 2001 Jason Diamond  http://injektilo.org/\r
-//\r
-\r
-namespace System.Xml\r
-{\r
-       public abstract class XmlReader\r
-       {\r
-               // properties\r
-\r
-               public abstract int AttributeCount { get; }\r
-\r
-               public abstract string BaseURI { get; }\r
-\r
-               public virtual bool CanResolveEntity\r
-               {\r
-                       get\r
-                       {\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-               public abstract int Depth { get; }\r
-\r
-               public abstract bool EOF { get; }\r
-\r
-               public virtual bool HasAttributes\r
-               {\r
-                       get\r
-                       {\r
-                               return AttributeCount > 0;\r
-                       }\r
-               }\r
-\r
-               public abstract bool HasValue { get; }\r
-\r
-               public abstract bool IsDefault { get; }\r
-\r
-               public abstract bool IsEmptyElement { get; }\r
-\r
-               public abstract string this[int i] { get; }\r
-\r
-               public abstract string this[string name] { get; }\r
-\r
-               public abstract string this[\r
-                       string localName,\r
-                       string namespaceName]\r
-               { get; }\r
-\r
-               public abstract string LocalName { get; }\r
-\r
-               public abstract string Name { get; }\r
-\r
-               public abstract string NamespaceURI { get; }\r
-\r
-               public abstract XmlNameTable NameTable { get; }\r
-\r
-               public abstract XmlNodeType NodeType { get; }\r
-\r
-               public abstract string Prefix { get; }\r
-\r
-               public abstract char QuoteChar { get; }\r
-\r
-               public abstract ReadState ReadState { get; }\r
-\r
-               public abstract string Value { get; }\r
-\r
-               public abstract string XmlLang { get; }\r
-\r
-               public abstract XmlSpace XmlSpace { get; }\r
-\r
-               // methods\r
-\r
-               public abstract void Close();\r
-\r
-               public abstract string GetAttribute(int i);\r
-\r
-               public abstract string GetAttribute(string name);\r
-\r
-               public abstract string GetAttribute(\r
-                       string localName,\r
-                       string namespaceName);\r
-\r
-               public static bool IsName(string s)\r
-               {\r
-                       bool result = false;\r
-\r
-                       if (s != null && s.Length > 0)\r
-                       {\r
-                               char[] chars = s.ToCharArray();\r
-\r
-                               if (XmlChar.IsFirstNameChar(chars[0]))\r
-                               {\r
-                                       int i = 1;\r
-                                       int n = chars.Length;\r
-\r
-                                       while (i < n && XmlChar.IsNameChar(chars[i]))\r
-                                       {\r
-                                               ++i;\r
-                                       }\r
-\r
-                                       result = i == n;\r
-                               }\r
-                       }\r
-\r
-                       return result;\r
-               }\r
-\r
-               public static bool IsNameToken(string s)\r
-               {\r
-                       bool result = false;\r
-\r
-                       if (s != null && s.Length > 0)\r
-                       {\r
-                               char[] chars = s.ToCharArray();\r
-\r
-                               int i = 0;\r
-                               int n = chars.Length;\r
-\r
-                               while (i < n && XmlChar.IsNameChar(chars[i]))\r
-                               {\r
-                                       ++i;\r
-                               }\r
-\r
-                               result = i == n;\r
-                       }\r
-\r
-                       return result;\r
-               }\r
-\r
-               public virtual bool IsStartElement()\r
-               {\r
-                       // TODO: implement me.\r
-                       return false;\r
-               }\r
-\r
-               public virtual bool IsStartElement(string name)\r
-               {\r
-                       // TODO: implement me.\r
-                       return false;\r
-               }\r
-\r
-               public virtual bool IsStartElement(\r
-                       string localName,\r
-                       string namespaceName)\r
-               {\r
-                       // TODO: implement me.\r
-                       return false;\r
-               }\r
-\r
-               public abstract string LookupNamespace(string prefix);\r
-\r
-               public abstract void MoveToAttribute(int i);\r
-\r
-               public abstract bool MoveToAttribute(string name);\r
-\r
-               public abstract bool MoveToAttribute(\r
-                       string localName,\r
-                       string namespaceName);\r
-\r
-               public virtual XmlNodeType MoveToContent()\r
-               {\r
-                       // TODO: implement me.\r
-                       return XmlNodeType.None;\r
-               }\r
-\r
-               public abstract bool MoveToElement();\r
-\r
-               public abstract bool MoveToFirstAttribute();\r
-\r
-               public abstract bool MoveToNextAttribute();\r
-\r
-               public abstract bool Read();\r
-\r
-               public abstract bool ReadAttributeValue();\r
-\r
-               public virtual string ReadElementString()\r
-               {\r
-                       // TODO: implement me.\r
-                       return null;\r
-               }\r
-\r
-               public virtual string ReadElementString(string name)\r
-               {\r
-                       // TODO: implement me.\r
-                       return null;\r
-               }\r
-\r
-               public virtual string ReadElementString(\r
-                       string localName,\r
-                       string namespaceName)\r
-               {\r
-                       // TODO: implement me.\r
-                       return null;\r
-               }\r
-\r
-               public virtual void ReadEndElement()\r
-               {\r
-                       // TODO: implement me.\r
-               }\r
-\r
-               public abstract string ReadInnerXml();\r
-\r
-               public abstract string ReadOuterXml();\r
-\r
-               public virtual void ReadStartElement()\r
-               {\r
-                       // TODO: implement me.\r
-               }\r
-\r
-               public virtual void ReadStartElement(string name)\r
-               {\r
-                       // TODO: implement me.\r
-               }\r
-\r
-               public virtual void ReadStartElement(\r
-                       string localName,\r
-                       string namespaceName)\r
-               {\r
-                       // TODO: implement me.\r
-               }\r
-\r
-               public abstract string ReadString();\r
-\r
-               public abstract void ResolveEntity();\r
-\r
-               public virtual void Skip()\r
-               {\r
-                       // TODO: implement me.\r
-               }\r
-       }\r
-}\r
+//
+// XmlReader.cs
+//
+// Authors:
+//     Jason Diamond (jason@injektilo.org)
+//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2001, 2002 Jason Diamond  http://injektilo.org/
+// (c) 2002 Ximian, Inc. (http://www.ximian.com)
+//
+
+namespace System.Xml
+{
+       public abstract class XmlReader
+       {
+               #region Constructor
+
+               protected XmlReader ()
+               {
+               }
+
+               #endregion
+
+               #region Properties
+
+               public abstract int AttributeCount { get; }
+
+               public abstract string BaseURI { get; }
+
+               public virtual bool CanResolveEntity
+               {
+                       get     { return false; }
+               }
+
+               public abstract int Depth { get; }
+
+               public abstract bool EOF { get; }
+
+               public virtual bool HasAttributes
+               {
+                       get { return AttributeCount > 0; }
+               }
+
+               public abstract bool HasValue { get; }
+
+               public abstract bool IsDefault { get; }
+
+               public abstract bool IsEmptyElement { get; }
+
+               public abstract string this[int i] { get; }
+
+               public abstract string this[string name] { get; }
+
+               public abstract string this[
+                       string localName,
+                       string namespaceName]
+               { get; }
+
+               public abstract string LocalName { get; }
+
+               public abstract string Name { get; }
+
+               public abstract string NamespaceURI { get; }
+
+               public abstract XmlNameTable NameTable { get; }
+
+               public abstract XmlNodeType NodeType { get; }
+
+               public abstract string Prefix { get; }
+
+               public abstract char QuoteChar { get; }
+
+               public abstract ReadState ReadState { get; }
+
+               public abstract string Value { get; }
+
+               public abstract string XmlLang { get; }
+
+               public abstract XmlSpace XmlSpace { get; }
+
+               #endregion
+
+               #region Methods
+
+               public abstract void Close ();
+
+               public abstract string GetAttribute (int i);
+
+               public abstract string GetAttribute (string name);
+
+               public abstract string GetAttribute (
+                       string localName,
+                       string namespaceName);
+
+               public static bool IsName (string s)
+               {
+                       bool result = false;
+
+                       if (s != null && s.Length > 0) {
+                               char[] chars = s.ToCharArray ();
+
+                               if (XmlChar.IsFirstNameChar (chars[0])) {
+                                       int i = 1;
+                                       int n = chars.Length;
+
+                                       while (i < n && XmlChar.IsNameChar (chars[i]))
+                                               ++i;
+
+                                       result = i == n;
+                               }
+                       }
+
+                       return result;
+               }
+
+               public static bool IsNameToken (string s)
+               {
+                       bool result = false;
+
+                       if (s != null && s.Length > 0) {
+                               char[] chars = s.ToCharArray ();
+
+                               int i = 0;
+                               int n = chars.Length;
+
+                               while (i < n && XmlChar.IsNameChar (chars[i]))
+                                       ++i;
+
+                               result = i == n;
+                       }
+
+                       return result;
+               }
+
+               public virtual bool IsStartElement ()
+               {
+                       return (MoveToContent () == XmlNodeType.Element);
+               }
+
+               public virtual bool IsStartElement (string name)
+               {
+                       if (!IsStartElement ())
+                               return false;
+
+                       return (Name == name);
+               }
+
+               public virtual bool IsStartElement (string localName, string namespaceName)
+               {
+                       if (!IsStartElement ())
+                               return false;
+
+                       return (LocalName == localName && NamespaceURI == namespaceName);
+               }
+
+               public abstract string LookupNamespace (string prefix);
+
+               public abstract void MoveToAttribute (int i);
+
+               public abstract bool MoveToAttribute (string name);
+
+               public abstract bool MoveToAttribute (
+                       string localName,
+                       string namespaceName);
+
+               private bool IsContent (XmlNodeType nodeType)
+               {
+                       /* MS doc says:
+                        * (non-white space text, CDATA, Element, EndElement, EntityReference, or EndEntity)
+                        */
+                       switch (nodeType) {
+                       case XmlNodeType.Text:
+                               return true;
+                       case XmlNodeType.CDATA:
+                               return true;
+                       case XmlNodeType.Element:
+                               return true;
+                       case XmlNodeType.EndElement:
+                               return true;
+                       case XmlNodeType.EntityReference:
+                               return true;
+                       case XmlNodeType.EndEntity:
+                               return true;
+                       }
+
+                       return false;
+               }
+
+               public virtual XmlNodeType MoveToContent ()
+               {
+                       do {
+                               XmlNodeType nodeType = NodeType;
+                               if (IsContent (nodeType))
+                                       return nodeType;
+                       } while (Read ());
+                       
+                       return XmlNodeType.None;
+               }
+
+               public abstract bool MoveToElement ();
+
+               public abstract bool MoveToFirstAttribute ();
+
+               public abstract bool MoveToNextAttribute ();
+
+               public abstract bool Read ();
+
+               public abstract bool ReadAttributeValue ();
+
+               public virtual string ReadElementString ()
+               {
+                       if (MoveToContent () != XmlNodeType.Element) {
+                               string error = String.Format ("'{0}' is an invalid node type.",
+                                                             NodeType.ToString ());
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       string result = String.Empty;
+                       if (!IsEmptyElement) {
+                               Read ();
+                               result = ReadString ();
+                               if (NodeType != XmlNodeType.EndElement) {
+                                       string error = String.Format ("'{0}' is an invalid node type.",
+                                                                     NodeType.ToString ());
+                                       throw new XmlException (this as IXmlLineInfo, error);
+                               }
+                       }
+
+                       Read ();
+                       return result;
+               }
+
+               public virtual string ReadElementString (string name)
+               {
+                       if (MoveToContent () != XmlNodeType.Element) {
+                               string error = String.Format ("'{0}' is an invalid node type.",
+                                                             NodeType.ToString ());
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       if (name != Name) {
+                               string error = String.Format ("The {0} tag from namespace {1} is expected.",
+                                                             Name, NamespaceURI);
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       string result = String.Empty;
+                       if (!IsEmptyElement) {
+                               Read ();
+                               result = ReadString ();
+                               if (NodeType != XmlNodeType.EndElement) {
+                                       string error = String.Format ("'{0}' is an invalid node type.",
+                                                                     NodeType.ToString ());
+                                       throw new XmlException (this as IXmlLineInfo, error);
+                               }
+                       }
+
+                       Read ();
+                       return result;
+               }
+
+               public virtual string ReadElementString (string localName, string namespaceName)
+               {
+                       if (MoveToContent () != XmlNodeType.Element) {
+                               string error = String.Format ("'{0}' is an invalid node type.",
+                                                             NodeType.ToString ());
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       if (localName != LocalName || NamespaceURI != namespaceName) {
+                               string error = String.Format ("The {0} tag from namespace {1} is expected.",
+                                                             LocalName, NamespaceURI);
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       string result = String.Empty;
+                       if (!IsEmptyElement) {
+                               Read ();
+                               result = ReadString ();
+                               if (NodeType != XmlNodeType.EndElement) {
+                                       string error = String.Format ("'{0}' is an invalid node type.",
+                                                                     NodeType.ToString ());
+                                       throw new XmlException (this as IXmlLineInfo, error);
+                               }
+                       }
+
+                       Read ();
+                       return result;
+               }
+
+               public virtual void ReadEndElement ()
+               {
+                       if (MoveToContent () != XmlNodeType.EndElement) {
+                               string error = String.Format ("'{0}' is an invalid node type.",
+                                                             NodeType.ToString ());
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       Read ();
+               }
+
+               public abstract string ReadInnerXml ();
+
+               public abstract string ReadOuterXml ();
+
+               public virtual void ReadStartElement ()
+               {
+                       if (MoveToContent () != XmlNodeType.Element) {
+                               string error = String.Format ("'{0}' is an invalid node type.",
+                                                             NodeType.ToString ());
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       Read ();
+               }
+
+               public virtual void ReadStartElement (string name)
+               {
+                       if (MoveToContent () != XmlNodeType.Element) {
+                               string error = String.Format ("'{0}' is an invalid node type.",
+                                                             NodeType.ToString ());
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       if (name != Name) {
+                               string error = String.Format ("The {0} tag from namespace {1} is expected.",
+                                                             Name, NamespaceURI);
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       Read ();
+               }
+
+               public virtual void ReadStartElement (string localName, string namespaceName)
+               {
+                       if (MoveToContent () != XmlNodeType.Element) {
+                               string error = String.Format ("'{0}' is an invalid node type.",
+                                                             NodeType.ToString ());
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       if (localName != LocalName || NamespaceURI != namespaceName) {
+                               string error = String.Format ("The {0} tag from namespace {1} is expected.",
+                                                             LocalName, NamespaceURI);
+                               throw new XmlException (this as IXmlLineInfo, error);
+                       }
+
+                       Read ();
+               }
+
+               public abstract string ReadString ();
+
+               public abstract void ResolveEntity ();
+
+               public virtual void Skip ()
+               {
+                       if (ReadState != ReadState.Interactive)
+                               return;
+
+                       MoveToElement ();
+                       if (NodeType != XmlNodeType.Element || IsEmptyElement) {
+                               Read ();
+                               return;
+                       }
+                               
+                       int depth = Depth;
+                       while (Read() && depth < Depth);
+                       if (NodeType == XmlNodeType.EndElement)
+                               Read ();
+               }
+
+               #endregion
+       }
+}