// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections;
+using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml.Schema; // only required for NET_2_0 (SchemaInfo)
using System.Xml.Serialization; // only required for NET_2_0 (SchemaInfo)
-using Mono.Xml; // only required for NET_2_0
using Mono.Xml.Schema; // only required for NET_2_0
+using Mono.Xml; // only required for NET_2_0
+#if NET_4_5
+using System.Threading;
+using System.Threading.Tasks;
+#endif
namespace System.Xml
{
get { return AttributeCount > 0; }
}
+#if NET_4_0
+ public virtual bool HasValue {
+ get {
+ switch (NodeType) {
+ case XmlNodeType.Attribute:
+ case XmlNodeType.Comment:
+ case XmlNodeType.ProcessingInstruction:
+ case XmlNodeType.SignificantWhitespace:
+ case XmlNodeType.CDATA:
+ case XmlNodeType.Text:
+ case XmlNodeType.Whitespace:
+ case XmlNodeType.XmlDeclaration:
+ return true;
+ }
+ return false;
+ }
+ }
+#else
public abstract bool HasValue { get; }
+#endif
+
+ public abstract bool IsEmptyElement { get; }
#if NET_2_0
public virtual bool IsDefault {
get { return false; }
}
- public virtual bool IsEmptyElement {
- get { return false; }
- }
-
public virtual string this [int i] {
get { return GetAttribute (i); }
}
#else
public abstract bool IsDefault { get; }
- public abstract bool IsEmptyElement { get; }
-
public abstract string this [int i] { get; }
public abstract string this [string name] { get; }
#region Methods
+#if NET_4_5
+ public virtual void Close ()
+ {
+ if (asyncRunning)
+ throw new InvalidOperationException ("An asynchronous operation is already in progress.");
+ }
+#else
public abstract void Close ();
+#endif
#if NET_2_0
private static XmlNameTable PopulateNameTable (
XmlNameTable nt = PopulateNameTable (settings);
return new XmlParserContext (nt,
new XmlNamespaceManager (nt),
+ null,
+ null,
+ null,
+ null,
baseUri,
- XmlSpace.None);
+ null,
+ XmlSpace.None,
+ null);
}
private static XmlNodeType GetNodeType (
XmlNodeType.Document;
}
- public static XmlReader Create (Stream stream)
+ public static XmlReader Create (Stream input)
+ {
+ return Create (input, null);
+ }
+
+ public static XmlReader Create (string inputUri)
{
- return Create (stream, null);
+ return Create (inputUri, null);
}
- public static XmlReader Create (string url)
+ public static XmlReader Create (TextReader input)
{
- return Create (url, null);
+ return Create (input, null);
}
- public static XmlReader Create (TextReader reader)
+ public static XmlReader Create (string inputUri, XmlReaderSettings settings)
{
- return Create (reader, null);
+ return Create (inputUri, settings, null);
}
- public static XmlReader Create (string url, XmlReaderSettings settings)
+ public static XmlReader Create (Stream input, XmlReaderSettings settings)
{
- return Create (url, settings, null);
+ return Create (input, settings, String.Empty);
}
- public static XmlReader Create (Stream stream, XmlReaderSettings settings)
+ public static XmlReader Create (TextReader input, XmlReaderSettings settings)
{
- return Create (stream, settings, String.Empty);
+ return Create (input, settings, String.Empty);
+ }
+
+ static XmlReaderSettings PopulateSettings (XmlReaderSettings src)
+ {
+ XmlReaderSettings copy;
+ if (src == null)
+ copy = new XmlReaderSettings ();
+ else
+ copy = src.Clone ();
+#if NET_4_5
+ copy.SetReadOnly ();
+#endif
+ return copy;
}
- public static XmlReader Create (TextReader reader, XmlReaderSettings settings)
+ static XmlReaderSettings PopulateSettings (XmlReader reader, XmlReaderSettings src)
{
- return Create (reader, settings, String.Empty);
+ XmlReaderSettings copy;
+ if (src == null)
+ copy = new XmlReaderSettings ();
+ else
+ copy = src.Clone ();
+#if NET_4_5
+ if (reader.Settings != null)
+ copy.Async = reader.Settings.Async;
+ copy.SetReadOnly ();
+#endif
+ return copy;
}
- public static XmlReader Create (Stream stream, XmlReaderSettings settings, string baseUri)
+ public static XmlReader Create (Stream input, XmlReaderSettings settings, string baseUri)
{
- if (settings == null)
- settings = new XmlReaderSettings ();
- return Create (stream, settings,
+ settings = PopulateSettings (settings);
+ return Create (input, settings,
PopulateParserContext (settings, baseUri));
}
- public static XmlReader Create (TextReader reader, XmlReaderSettings settings, string baseUri)
+ public static XmlReader Create (TextReader input, XmlReaderSettings settings, string baseUri)
{
- if (settings == null)
- settings = new XmlReaderSettings ();
- return Create (reader, settings,
+ settings = PopulateSettings (settings);
+ return Create (input, settings,
PopulateParserContext (settings, baseUri));
}
- [MonoTODO ("ConformanceLevel")]
public static XmlReader Create (XmlReader reader, XmlReaderSettings settings)
{
- if (settings == null)
- settings = new XmlReaderSettings ();
+ settings = PopulateSettings (reader, settings);
XmlReader r = CreateFilteredXmlReader (reader, settings);
r.settings = settings;
return r;
}
- [MonoTODO ("ConformanceLevel")]
- public static XmlReader Create (string url, XmlReaderSettings settings, XmlParserContext context)
+ public static XmlReader Create (string inputUri, XmlReaderSettings settings, XmlParserContext inputContext)
{
- if (settings == null)
- settings = new XmlReaderSettings ();
- if (context == null)
- context = PopulateParserContext (settings, url);
- return CreateCustomizedTextReader (
- new XmlTextReader (true, url, GetNodeType (settings), context),
- settings);
+ settings = PopulateSettings (settings);
+ bool closeInputBak = settings.CloseInput;
+ try {
+ settings.CloseInput = true; // forced. See XmlReaderCommonTests.CreateFromUrlClose().
+ if (inputContext == null)
+ inputContext = PopulateParserContext (settings, inputUri);
+ XmlTextReader xtr = new XmlTextReader (false, settings.XmlResolver, inputUri, GetNodeType (settings), inputContext);
+ XmlReader ret = CreateCustomizedTextReader (xtr, settings);
+ return ret;
+ } finally {
+ settings.CloseInput = closeInputBak;
+ }
}
- [MonoTODO ("ConformanceLevel")]
- public static XmlReader Create (Stream stream, XmlReaderSettings settings, XmlParserContext context)
+ public static XmlReader Create (Stream input, XmlReaderSettings settings, XmlParserContext inputContext)
{
- if (settings == null)
- settings = new XmlReaderSettings ();
- if (context == null)
- context = PopulateParserContext (settings, String.Empty);
- return CreateCustomizedTextReader (new XmlTextReader (stream, GetNodeType (settings), context), settings);
+ settings = PopulateSettings (settings);
+ if (inputContext == null)
+ inputContext = PopulateParserContext (settings, String.Empty);
+ return CreateCustomizedTextReader (new XmlTextReader (input, GetNodeType (settings), inputContext), settings);
}
- [MonoTODO ("ConformanceLevel")]
- public static XmlReader Create (TextReader reader, XmlReaderSettings settings, XmlParserContext context)
+ public static XmlReader Create (TextReader input, XmlReaderSettings settings, XmlParserContext inputContext)
{
- if (settings == null)
- settings = new XmlReaderSettings ();
- if (context == null)
- context = PopulateParserContext (settings, String.Empty);
- return CreateCustomizedTextReader (new XmlTextReader (context.BaseURI, reader, GetNodeType (settings), context), settings);
+ settings = PopulateSettings (settings);
+ if (inputContext == null)
+ inputContext = PopulateParserContext (settings, String.Empty);
+ return CreateCustomizedTextReader (new XmlTextReader (inputContext.BaseURI, input, GetNodeType (settings), inputContext), settings);
}
private static XmlReader CreateCustomizedTextReader (XmlTextReader reader, XmlReaderSettings settings)
reader.XmlResolver = settings.XmlResolver;
// Normalization is set true by default.
reader.Normalization = true;
+ reader.EntityHandling = EntityHandling.ExpandEntities;
if (settings.ProhibitDtd)
reader.ProhibitDtd = true;
private static XmlReader CreateFilteredXmlReader (XmlReader reader, XmlReaderSettings settings)
{
+ ConformanceLevel conf = ConformanceLevel.Auto;
+ if (reader is XmlTextReader)
+ conf = ((XmlTextReader) reader).Conformance;
+ else if (reader.Settings != null)
+ conf = reader.Settings.ConformanceLevel;
+ else
+ conf = settings.ConformanceLevel;
+ if (settings.ConformanceLevel != ConformanceLevel.Auto &&
+ conf != settings.ConformanceLevel)
+ throw new InvalidOperationException (String.Format ("ConformanceLevel cannot be overwritten by a wrapping XmlReader. The source reader has {0}, while {1} is specified.", conf, settings.ConformanceLevel));
+ settings.ConformanceLevel = conf;
+
reader = CreateValidatingXmlReader (reader, settings);
- if (reader.Settings != null ||
- settings.IgnoreComments ||
- settings.IgnoreProcessingInstructions ||
- settings.IgnoreWhitespace)
+ if ( settings.IgnoreComments ||
+ settings.IgnoreProcessingInstructions ||
+ settings.IgnoreWhitespace)
return new XmlFilterReader (reader, settings);
else {
reader.settings = settings;
{
XmlValidatingReader xvr = null;
switch (settings.ValidationType) {
- case ValidationType.None:
+ // Auto and XDR are obsoleted in 2.0 and therefore ignored.
+ default:
return reader;
case ValidationType.DTD:
xvr = new XmlValidatingReader (reader);
xvr.ValidationType = ValidationType.DTD;
break;
case ValidationType.Schema:
-// xvr = new XmlValidatingReader (reader);
-// xvr.ValidationType = ValidationType.Schema;
return new XmlSchemaValidatingReader (reader, settings);
- case ValidationType.Auto:
- xvr = new XmlValidatingReader (reader);
- xvr.ValidationType = ValidationType.DTD;
- reader = xvr;
- goto case ValidationType.Schema;
- case ValidationType.XDR:
- throw new NotSupportedException ();
}
- if (xvr != null)
- xvr.SetSchemas (settings.Schemas);
// Actually I don't think they are treated in DTD validation though...
if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessIdentityConstraints) == 0)
throw new NotImplementedException ();
- if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessInlineSchema) != 0)
- throw new NotImplementedException ();
- if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessSchemaLocation) != 0)
- throw new NotImplementedException ();
- if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessValidationWarnings) == 0)
- throw new NotImplementedException ();
+ //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessInlineSchema) != 0)
+ // throw new NotImplementedException ();
+ //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessSchemaLocation) != 0)
+ // throw new NotImplementedException ();
+ //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ReportValidationWarnings) == 0)
+ // throw new NotImplementedException ();
return xvr != null ? xvr : reader;
}
-#endif
-#if NET_2_0
- void IDisposable.Dispose ()
+#if NET_4_0
+ public void Dispose ()
+#else
+ void IDisposable.Dispose()
+#endif
{
Dispose (false);
}
public abstract string GetAttribute (string name);
- public abstract string GetAttribute (
- string localName,
- string namespaceName);
+ public abstract string GetAttribute (string name, string namespaceURI);
- public static bool IsName (string s)
+ public static bool IsName (string str)
{
- return s != null && XmlChar.IsName (s);
+ return str != null && XmlChar.IsName (str);
}
- public static bool IsNameToken (string s)
+ public static bool IsNameToken (string str)
{
- return s != null && XmlChar.IsNmToken (s);
+ return str != null && XmlChar.IsNmToken (str);
}
public virtual bool IsStartElement ()
return (Name == name);
}
- public virtual bool IsStartElement (string localName, string namespaceName)
+ public virtual bool IsStartElement (string localname, string ns)
{
if (!IsStartElement ())
return false;
- return (LocalName == localName && NamespaceURI == namespaceName);
+ return (LocalName == localname && NamespaceURI == ns);
}
public abstract string LookupNamespace (string prefix);
#if NET_2_0
- public virtual string LookupNamespace (string prefix, bool atomizedNames)
-#else
- internal virtual string LookupNamespace (string prefix, bool atomizedNames)
-#endif
+ public virtual void MoveToAttribute (int i)
{
- return LookupNamespace (prefix);
+ if (i >= AttributeCount)
+ throw new ArgumentOutOfRangeException ();
+ MoveToFirstAttribute ();
+ for (int a = 0; a < i; a++)
+ MoveToNextAttribute ();
}
-
+#else
public abstract void MoveToAttribute (int i);
+#endif
public abstract bool MoveToAttribute (string name);
- public abstract bool MoveToAttribute (
- string localName,
- string namespaceName);
+ public abstract bool MoveToAttribute (string name, string ns);
private bool IsContent (XmlNodeType nodeType)
{
public virtual XmlNodeType MoveToContent ()
{
+ switch (ReadState) {
+ case ReadState.Initial:
+ case ReadState.Interactive:
+ break;
+ default:
+ return NodeType;
+ }
+
if (NodeType == XmlNodeType.Attribute)
MoveToElement ();
return result;
}
- public virtual string ReadElementString (string localName, string namespaceName)
+ public virtual string ReadElementString (string localname, string ns)
{
if (MoveToContent () != XmlNodeType.Element) {
string error = String.Format ("'{0}' is an invalid node type.",
throw XmlError (error);
}
- if (localName != LocalName || NamespaceURI != namespaceName) {
+ if (localname != LocalName || NamespaceURI != ns) {
string error = String.Format ("The {0} tag from namespace {1} is expected.",
LocalName, NamespaceURI);
throw XmlError (error);
Read ();
}
-#if NET_1_0
- public abstract string ReadInnerXml ();
-
- public abstract string ReadOuterXml ();
-
-#else
public virtual string ReadInnerXml ()
- {
- return ReadInnerXmlInternal ();
- }
-
- public virtual string ReadOuterXml ()
- {
- return ReadOuterXmlInternal ();
- }
-#endif
-
- internal string ReadInnerXmlInternal ()
{
if (ReadState != ReadState.Interactive || NodeType == XmlNodeType.EndElement)
return String.Empty;
+ if (IsEmptyElement) {
+ Read ();
+ return String.Empty;
+ }
StringWriter sw = new StringWriter ();
XmlTextWriter xtw = new XmlTextWriter (sw);
if (NodeType == XmlNodeType.Element) {
- if (IsEmptyElement) {
- Read ();
- return String.Empty;
- }
int startDepth = Depth;
Read ();
while (startDepth < Depth) {
return sw.ToString ();
}
- internal string ReadOuterXmlInternal ()
+ public virtual string ReadOuterXml ()
{
if (ReadState != ReadState.Interactive || NodeType == XmlNodeType.EndElement)
return String.Empty;
- StringWriter sw = new StringWriter ();
- XmlTextWriter xtw = new XmlTextWriter (sw);
- xtw.WriteNode (this, false);
- return sw.ToString ();
+ switch (NodeType) {
+ case XmlNodeType.Element:
+ case XmlNodeType.Attribute:
+ StringWriter sw = new StringWriter ();
+ XmlTextWriter xtw = new XmlTextWriter (sw);
+ xtw.WriteNode (this, false);
+ return sw.ToString ();
+ default:
+ Skip ();
+ return String.Empty;
+ }
}
public virtual void ReadStartElement ()
Read ();
}
- public virtual void ReadStartElement (string localName, string namespaceName)
+ public virtual void ReadStartElement (string localname, string ns)
{
if (MoveToContent () != XmlNodeType.Element) {
string error = String.Format ("'{0}' is an invalid node type.",
throw XmlError (error);
}
- if (localName != LocalName || NamespaceURI != namespaceName) {
+ if (localname != LocalName || NamespaceURI != ns) {
string error = String.Format ("Expecting {0} tag from namespace {1}, got {2} and {3} instead",
- localName, namespaceName,
+ localname, ns,
LocalName, NamespaceURI);
throw XmlError (error);
}
Read ();
}
-#if NET_1_0
- public abstract string ReadString ();
-#else
public virtual string ReadString ()
- {
- return ReadStringInternal ();
- }
-#endif
-
- internal string ReadStringInternal ()
{
if (readStringBuffer == null)
readStringBuffer = new StringBuilder ();
get { return typeof (string); }
}
- [MonoTODO]
public virtual bool ReadToDescendant (string name)
{
+ if (ReadState == ReadState.Initial) {
+ MoveToContent ();
+ if (IsStartElement (name))
+ return true;
+ }
if (NodeType != XmlNodeType.Element || IsEmptyElement)
return false;
int depth = Depth;
return false;
}
- [MonoTODO]
public virtual bool ReadToDescendant (string localName, string namespaceURI)
{
+ if (ReadState == ReadState.Initial) {
+ MoveToContent ();
+ if (IsStartElement (localName, namespaceURI))
+ return true;
+ }
if (NodeType != XmlNodeType.Element || IsEmptyElement)
return false;
int depth = Depth;
return false;
}
- [MonoTODO]
public virtual bool ReadToFollowing (string name)
{
while (Read ())
return false;
}
- [MonoTODO]
public virtual bool ReadToFollowing (string localName, string namespaceURI)
{
while (Read ())
- if (NodeType == XmlNodeType.Element && localName == Name && namespaceURI == NamespaceURI)
+ if (NodeType == XmlNodeType.Element && localName == LocalName && namespaceURI == NamespaceURI)
return true;
return false;
}
- [MonoTODO]
public virtual bool ReadToNextSibling (string name)
{
- if (NodeType != XmlNodeType.Element || IsEmptyElement)
+ if (ReadState != ReadState.Interactive)
return false;
+ MoveToElement ();
int depth = Depth;
- for (Skip (); depth < Depth; Skip ())
+ Skip ();
+ for (; !EOF && depth <= Depth; Skip ())
if (NodeType == XmlNodeType.Element && name == Name)
return true;
return false;
}
- [MonoTODO]
public virtual bool ReadToNextSibling (string localName, string namespaceURI)
{
- if (NodeType != XmlNodeType.Element || IsEmptyElement)
+ if (ReadState != ReadState.Interactive)
return false;
int depth = Depth;
- for (Skip (); depth < Depth; Skip ())
+ Skip ();
+ for (; !EOF && depth <= Depth; Skip ())
if (NodeType == XmlNodeType.Element && localName == LocalName && namespaceURI == NamespaceURI)
return true;
return false;
}
- [MonoTODO]
public virtual XmlReader ReadSubtree ()
{
+ if (NodeType != XmlNodeType.Element)
+ throw new InvalidOperationException (String.Format ("ReadSubtree() can be invoked only when the reader is positioned on an element. Current node is {0}. {1}", NodeType, GetLocation ()));
return new SubtreeXmlReader (this);
}
- [MonoTODO]
- [Obsolete]
- public virtual object ReadTypedValue ()
+ private string ReadContentString ()
{
- if (NodeType == XmlNodeType.Element)
- return ReadElementContentAs (ValueType, this as IXmlNamespaceResolver);
- else
- return ReadContentAs (ValueType, this as IXmlNamespaceResolver);
+ // The latter condition indicates that this XmlReader is on an attribute value
+ // (HasAttributes is to indicate it is on attribute value).
+ if (NodeType == XmlNodeType.Attribute || NodeType != XmlNodeType.Element && HasAttributes)
+ return Value;
+ return ReadContentString (true);
}
- private string ReadContentString ()
+ private string ReadContentString (bool isText)
{
- switch (NodeType) {
- case XmlNodeType.Text:
- case XmlNodeType.CDATA:
- case XmlNodeType.SignificantWhitespace:
- case XmlNodeType.Whitespace:
- break;
- default:
- throw new InvalidOperationException (String.Format ("This method does not support node type {0}.", NodeType));
+ if (isText) {
+ switch (NodeType) {
+ case XmlNodeType.Text:
+ case XmlNodeType.SignificantWhitespace:
+ case XmlNodeType.Whitespace:
+ case XmlNodeType.CDATA:
+ break;
+ case XmlNodeType.Element:
+ throw new InvalidOperationException (String.Format ("Node type {0} is not supported in this operation.{1}", NodeType, GetLocation ()));
+ default:
+ return String.Empty;
+ }
}
- return ReadString ();
+
+ string value = String.Empty;
+ do {
+ switch (NodeType) {
+ case XmlNodeType.Element:
+ if (isText)
+ return value;
+ throw XmlError ("Child element is not expected in this operation.");
+ case XmlNodeType.EndElement:
+ return value;
+ case XmlNodeType.Text:
+ case XmlNodeType.CDATA:
+ case XmlNodeType.SignificantWhitespace:
+ case XmlNodeType.Whitespace:
+ value += Value;
+ break;
+ }
+ } while (Read ());
+ throw XmlError ("Unexpected end of document.");
+ }
+
+ string GetLocation ()
+ {
+ IXmlLineInfo li = this as IXmlLineInfo;
+ return li != null && li.HasLineInfo () ?
+ String.Format (" {0} (line {1}, column {2})", BaseURI, li.LineNumber, li.LinePosition) : String.Empty;
}
[MonoTODO]
- public virtual object ReadElementContentAs (Type type, IXmlNamespaceResolver resolver)
+ public virtual object ReadElementContentAsObject ()
{
- return ValueAs (ReadElementString (), type, resolver);
+ return ReadElementContentAs (ValueType, null);
}
[MonoTODO]
- public virtual object ReadElementContentAs (Type type, IXmlNamespaceResolver resolver, string localName, string namespaceURI)
+ public virtual object ReadElementContentAsObject (string localName, string namespaceURI)
{
- return ValueAs (ReadElementString (localName, namespaceURI), type, resolver);
+ return ReadElementContentAs (ValueType, null, localName, namespaceURI);
}
[MonoTODO]
- public virtual object ReadContentAs (Type type, IXmlNamespaceResolver resolver)
+ public virtual object ReadContentAsObject ()
{
- return ValueAs (ReadContentString (), type, resolver);
+ return ReadContentAs (ValueType, null);
}
- private object ValueAs (string text, Type type, IXmlNamespaceResolver resolver)
+#if NET_4_5
+ public virtual DateTimeOffset ReadContentAsDateTimeOffset ()
{
try {
- if (type == typeof (XmlQualifiedName))
- return XmlQualifiedName.Parse (text, resolver);
+ return XmlConvert.ToDateTimeOffset (ReadContentString ());
+ } catch (Exception e) {
+ throw XmlError ("Typed value is invalid.", e);
+ }
+ }
+#endif
+
+ public virtual object ReadElementContentAs (Type returnType, IXmlNamespaceResolver namespaceResolver)
+ {
+ bool isEmpty = IsEmptyElement;
+ ReadStartElement ();
+ object obj = ValueAs (isEmpty ? String.Empty : ReadContentString (false), returnType, namespaceResolver, false);
+ if (!isEmpty)
+ ReadEndElement ();
+ return obj;
+ }
+
+ public virtual object ReadElementContentAs (Type returnType, IXmlNamespaceResolver namespaceResolver, string localName, string namespaceURI)
+ {
+ if (localName == null)
+ throw new ArgumentNullException ("localName");
+ if (namespaceURI == null)
+ throw new ArgumentNullException ("namespaceURI");
+
+ bool isEmpty = IsEmptyElement;
+ ReadStartElement (localName, namespaceURI);
+ if (isEmpty)
+ return ValueAs (String.Empty, returnType, namespaceResolver, false);
+ object obj = ReadContentAs (returnType, namespaceResolver);
+ ReadEndElement ();
+ return obj;
+ }
+
+ public virtual object ReadContentAs (Type returnType, IXmlNamespaceResolver namespaceResolver)
+ {
+ return ValueAs (ReadContentString (), returnType, namespaceResolver, false);
+ }
+
+ private object ValueAs (string text, Type type, IXmlNamespaceResolver resolver, bool isArrayItem)
+ {
+ try {
+ if (type == typeof (object))
+ return text;
+ if (type.IsArray && !isArrayItem) {
+ var elemType = type.GetElementType ();
+ var sarr = text.Split ((string []) null, StringSplitOptions.RemoveEmptyEntries);
+ var ret = Array.CreateInstance (elemType, sarr.Length);
+ for (int i = 0; i < ret.Length; i++)
+ ret.SetValue (ValueAs (sarr [i], elemType, resolver, true), i);
+ return ret;
+ }
+
+ if (type == typeof (XmlQualifiedName)) {
+ if (resolver != null)
+ return XmlQualifiedName.Parse (text, resolver, true);
+ else
+ return XmlQualifiedName.Parse (text, this, true);
+ }
+ if (type == typeof (Uri))
+ return XmlConvert.ToUri (text);
+ if (type == typeof (TimeSpan))
+ return XmlConvert.ToTimeSpan (text);
+ if (type == typeof (DateTimeOffset))
+ return XmlConvert.ToDateTimeOffset (text);
switch (Type.GetTypeCode (type)) {
case TypeCode.Boolean:
- return ReadContentAsBoolean ();
+ return XQueryConvert.StringToBoolean (text);
+ case TypeCode.Byte:
+ return XmlConvert.ToByte (text);
+ case TypeCode.SByte:
+ return XmlConvert.ToSByte (text);
+ case TypeCode.Int16:
+ return XmlConvert.ToInt16 (text);
+ case TypeCode.UInt16:
+ return XQueryConvert.StringToUnsignedShort (text);
+ case TypeCode.Int32:
+ return XQueryConvert.StringToInt (text);
+ case TypeCode.UInt32:
+ return XQueryConvert.StringToUnsignedInt (text);
+ case TypeCode.Int64:
+ return XQueryConvert.StringToInteger (text);
+ case TypeCode.UInt64:
+ return XQueryConvert.StringToUnsignedLong (text);
case TypeCode.DateTime:
- return ReadContentAsDateTime ();
+ return XQueryConvert.StringToDateTime (text);
case TypeCode.Decimal:
- return ReadContentAsDecimal ();
+ return XQueryConvert.StringToDecimal (text);
case TypeCode.Double:
- return ReadContentAsDouble ();
- case TypeCode.Int32:
- return ReadContentAsInt ();
- case TypeCode.Int64:
- return ReadContentAsLong ();
+ return XQueryConvert.StringToDouble (text);
case TypeCode.Single:
- return ReadContentAsFloat ();
+ return XQueryConvert.StringToFloat (text);
case TypeCode.String:
- return ReadContentAsString ();
+ return text;
}
} catch (Exception ex) {
- return new FormatException (String.Format ("Current text value '{0}' is not acceptable for specified type '{1}'.", text, type));
+ throw XmlError (String.Format ("Current text value '{0}' is not acceptable for specified type '{1}'. {2}", text, type, ex != null ? ex.Message : String.Empty), ex);
}
- throw new ArgumentException (String.Format ("Specified type '{0}' is not supported.", type));
+ throw new XmlException (String.Format ("Specified type '{0}' is not supported.", type));
}
- [MonoTODO]
public virtual bool ReadElementContentAsBoolean ()
{
- return XQueryConvert.StringToBoolean (ReadElementString ());
+ try {
+ return XQueryConvert.StringToBoolean (ReadElementContentAsString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual DateTime ReadElementContentAsDateTime ()
{
- return XQueryConvert.StringToDateTime (ReadElementString ());
+ try {
+ return XQueryConvert.StringToDateTime (ReadElementContentAsString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual decimal ReadElementContentAsDecimal ()
{
- return XQueryConvert.StringToDecimal (ReadElementString ());
+ try {
+ return XQueryConvert.StringToDecimal (ReadElementContentAsString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual double ReadElementContentAsDouble ()
{
- return XQueryConvert.StringToDouble (ReadElementString ());
+ try {
+ return XQueryConvert.StringToDouble (ReadElementContentAsString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual float ReadElementContentAsFloat ()
{
- return XQueryConvert.StringToFloat (ReadElementString ());
+ try {
+ return XQueryConvert.StringToFloat (ReadElementContentAsString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual int ReadElementContentAsInt ()
{
- return XQueryConvert.StringToInt (ReadElementString ());
+ try {
+ return XQueryConvert.StringToInt (ReadElementContentAsString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual long ReadElementContentAsLong ()
{
- return XQueryConvert.StringToInteger (ReadElementString ());
+ try {
+ return XQueryConvert.StringToInteger (ReadElementContentAsString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual string ReadElementContentAsString ()
{
- return ReadElementString ();
+ bool isEmpty = IsEmptyElement;
+ // unlike ReadStartElement() it rejects non-content nodes (this check is done before MoveToContent())
+ if (NodeType != XmlNodeType.Element)
+ throw new InvalidOperationException (String.Format ("'{0}' is an element node.", NodeType));
+ ReadStartElement ();
+ if (isEmpty)
+ return String.Empty;
+ string s = ReadContentString (false);
+ ReadEndElement ();
+ return s;
}
- [MonoTODO]
public virtual bool ReadElementContentAsBoolean (string localName, string namespaceURI)
{
- return XQueryConvert.StringToBoolean (ReadElementString (localName, namespaceURI));
+ try {
+ return XQueryConvert.StringToBoolean (ReadElementContentAsString (localName, namespaceURI));
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual DateTime ReadElementContentAsDateTime (string localName, string namespaceURI)
{
- return XQueryConvert.StringToDateTime (ReadElementString (localName, namespaceURI));
+ try {
+ return XQueryConvert.StringToDateTime (ReadElementContentAsString (localName, namespaceURI));
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual decimal ReadElementContentAsDecimal (string localName, string namespaceURI)
{
- return XQueryConvert.StringToDecimal (ReadElementString (localName, namespaceURI));
+ try {
+ return XQueryConvert.StringToDecimal (ReadElementContentAsString (localName, namespaceURI));
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual double ReadElementContentAsDouble (string localName, string namespaceURI)
{
- return XQueryConvert.StringToDouble (ReadElementString (localName, namespaceURI));
+ try {
+ return XQueryConvert.StringToDouble (ReadElementContentAsString (localName, namespaceURI));
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual float ReadElementContentAsFloat (string localName, string namespaceURI)
{
- return XQueryConvert.StringToFloat (ReadElementString (localName, namespaceURI));
+ try {
+ return XQueryConvert.StringToFloat (ReadElementContentAsString (localName, namespaceURI));
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual int ReadElementContentAsInt (string localName, string namespaceURI)
{
- return XQueryConvert.StringToInt (ReadElementString (localName, namespaceURI));
+ try {
+ return XQueryConvert.StringToInt (ReadElementContentAsString (localName, namespaceURI));
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual long ReadElementContentAsLong (string localName, string namespaceURI)
{
- return XQueryConvert.StringToInteger (ReadElementString (localName, namespaceURI));
+ try {
+ return XQueryConvert.StringToInteger (ReadElementContentAsString (localName, namespaceURI));
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual string ReadElementContentAsString (string localName, string namespaceURI)
{
- return ReadElementString (localName, namespaceURI);
+ bool isEmpty = IsEmptyElement;
+ // unlike ReadStartElement() it rejects non-content nodes (this check is done before MoveToContent())
+ if (NodeType != XmlNodeType.Element)
+ throw new InvalidOperationException (String.Format ("'{0}' is an element node.", NodeType));
+ ReadStartElement (localName, namespaceURI);
+ if (isEmpty)
+ return String.Empty;
+ string s = ReadContentString (false);
+ ReadEndElement ();
+ return s;
}
- [MonoTODO]
public virtual bool ReadContentAsBoolean ()
{
- return XQueryConvert.StringToBoolean (ReadContentString ());
+ try {
+ return XQueryConvert.StringToBoolean (ReadContentString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual DateTime ReadContentAsDateTime ()
{
- return XQueryConvert.StringToDateTime (ReadContentString ());
+ try {
+ return XQueryConvert.StringToDateTime (ReadContentString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual decimal ReadContentAsDecimal ()
{
- return XQueryConvert.StringToDecimal (ReadContentString ());
+ try {
+ return XQueryConvert.StringToDecimal (ReadContentString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual double ReadContentAsDouble ()
{
- return XQueryConvert.StringToDouble (ReadContentString ());
+ try {
+ return XQueryConvert.StringToDouble (ReadContentString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual float ReadContentAsFloat ()
{
- return XQueryConvert.StringToFloat (ReadContentString ());
+ try {
+ return XQueryConvert.StringToFloat (ReadContentString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual int ReadContentAsInt ()
{
- return XQueryConvert.StringToInt (ReadContentString ());
+ try {
+ return XQueryConvert.StringToInt (ReadContentString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual long ReadContentAsLong ()
{
- return XQueryConvert.StringToInteger (ReadContentString ());
+ try {
+ return XQueryConvert.StringToInteger (ReadContentString ());
+ } catch (FormatException ex) {
+ throw XmlError ("Typed value is invalid.", ex);
+ }
}
- [MonoTODO]
public virtual string ReadContentAsString ()
{
return ReadContentString ();
}
public virtual int ReadContentAsBase64 (
- byte [] buffer, int offset, int length)
+ byte [] buffer, int index, int count)
{
CheckSupport ();
return binary.ReadContentAsBase64 (
- buffer, offset, length);
+ buffer, index, count);
}
public virtual int ReadContentAsBinHex (
- byte [] buffer, int offset, int length)
+ byte [] buffer, int index, int count)
{
CheckSupport ();
return binary.ReadContentAsBinHex (
- buffer, offset, length);
+ buffer, index, count);
}
public virtual int ReadElementContentAsBase64 (
- byte [] buffer, int offset, int length)
+ byte [] buffer, int index, int count)
{
CheckSupport ();
return binary.ReadElementContentAsBase64 (
- buffer, offset, length);
+ buffer, index, count);
}
public virtual int ReadElementContentAsBinHex (
- byte [] buffer, int offset, int length)
+ byte [] buffer, int index, int count)
{
CheckSupport ();
return binary.ReadElementContentAsBinHex (
- buffer, offset, length);
+ buffer, index, count);
}
-#endif
-#if NET_2_0
- public virtual int ReadValueChunk (
- char [] buffer, int offset, int length)
-#else
- internal virtual int ReadValueChunk (
- char [] buffer, int offset, int length)
-#endif
+ private void CheckSupport ()
{
- if (!CanReadValueChunk)
+ // Default implementation expects both.
+ if (!CanReadBinaryContent || !CanReadValueChunk)
throw new NotSupportedException ();
if (binary == null)
binary = new XmlReaderBinarySupport (this);
- return binary.ReadValueChunk (buffer, offset, length);
}
+
+#endif
- private void CheckSupport ()
+ public virtual int ReadValueChunk (char [] buffer, int index, int count)
{
- // Default implementation expects both.
- if (!CanReadBinaryContent || !CanReadValueChunk)
+ if (!CanReadValueChunk)
throw new NotSupportedException ();
if (binary == null)
binary = new XmlReaderBinarySupport (this);
+ return binary.ReadValueChunk (buffer, index, count);
}
public abstract void ResolveEntity ();
{
return new XmlException (this as IXmlLineInfo, BaseURI, message);
}
+#if NET_2_0
+ private XmlException XmlError (string message, Exception innerException)
+ {
+ return new XmlException (this as IXmlLineInfo, BaseURI, message);
+ }
+#endif
+ #endregion
+
+#if NET_4_5
+ #region .NET 4.5 Async Methods
+
+ bool asyncRunning;
+
+ void StartAsync ()
+ {
+ if (!settings.Async)
+ throw new InvalidOperationException ("Set XmlReaderSettings.Async to true if you want to use Async Methods.");
+ lock (this) {
+ if (asyncRunning)
+ throw new InvalidOperationException ("An asynchronous operation is already in progress.");
+ asyncRunning = true;
+ }
+ }
+
+ public virtual Task<bool> ReadAsync ()
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return Read ();
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<string> GetValueAsync ()
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return Value;
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<string> ReadInnerXmlAsync ()
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadInnerXml ();
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<string> ReadOuterXmlAsync ()
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadOuterXml ();
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<string> ReadContentAsStringAsync ()
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadContentAsString ();
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<int> ReadContentAsBase64Async (byte[] buffer, int index, int count)
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadContentAsBase64 (buffer, index, count);
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<int> ReadContentAsBinHexAsync (byte[] buffer, int index, int count)
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadContentAsBinHex (buffer, index, count);
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<int> ReadElementContentAsBase64Async (byte[] buffer, int index, int count)
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadElementContentAsBase64 (buffer, index, count);
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<int> ReadElementContentAsBinHexAsync (byte[] buffer, int index, int count)
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadElementContentAsBinHex (buffer, index, count);
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<int> ReadValueChunkAsync (char[] buffer, int index, int count)
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadValueChunk (buffer, index, count);
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<object> ReadContentAsAsync (Type returnType, IXmlNamespaceResolver namespaceResolver)
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadContentAs (returnType, namespaceResolver);
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<object> ReadContentAsObjectAsync ()
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadContentAsObject ();
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<object> ReadElementContentAsAsync (Type returnType, IXmlNamespaceResolver namespaceResolver)
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadElementContentAs (returnType, namespaceResolver);
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<object> ReadElementContentAsObjectAsync ()
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadElementContentAsObject ();
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<string> ReadElementContentAsStringAsync ()
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return ReadElementContentAsString ();
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task<XmlNodeType> MoveToContentAsync ()
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ return MoveToContent ();
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
+
+ public virtual Task SkipAsync ()
+ {
+ StartAsync ();
+ return Task.Run (() => {
+ try {
+ Skip ();
+ } finally {
+ asyncRunning = false;
+ }
+ });
+ }
#endregion
+#endif
}
}