5 // Jason Diamond (jason@injektilo.org)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
9 // (C) 2001, 2002 Jason Diamond http://injektilo.org/
10 // (c) 2002 Ximian, Inc. (http://www.ximian.com)
11 // (C) 2003 Atsushi Enomoto
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
35 using System.Diagnostics;
38 using System.Xml.Schema; // only required for NET_2_0 (SchemaInfo)
39 using System.Xml.Serialization; // only required for NET_2_0 (SchemaInfo)
40 using Mono.Xml.Schema; // only required for NET_2_0
41 using Mono.Xml; // only required for NET_2_0
43 using System.Threading;
44 using System.Threading.Tasks;
50 public abstract class XmlReader : IDisposable
52 public abstract class XmlReader
55 private StringBuilder readStringBuffer;
56 private XmlReaderBinarySupport binary;
58 private XmlReaderSettings settings;
63 protected XmlReader ()
71 public abstract int AttributeCount { get; }
73 public abstract string BaseURI { get; }
75 internal XmlReaderBinarySupport Binary {
76 get { return binary; }
79 internal XmlReaderBinarySupport.CharGetter BinaryCharGetter {
80 get { return binary != null ? binary.Getter : null; }
83 binary = new XmlReaderBinarySupport (this);
84 binary.Getter = value;
89 // To enable it internally in sys.xml, just insert these
90 // two lines into Read():
93 // if (Binary != null)
97 public virtual bool CanReadBinaryContent {
101 public virtual bool CanReadValueChunk {
102 get { return false; }
105 internal virtual bool CanReadBinaryContent {
106 get { return false; }
109 internal virtual bool CanReadValueChunk {
110 get { return false; }
114 public virtual bool CanResolveEntity
116 get { return false; }
119 public abstract int Depth { get; }
121 public abstract bool EOF { get; }
123 public virtual bool HasAttributes
125 get { return AttributeCount > 0; }
129 public virtual bool HasValue {
132 case XmlNodeType.Attribute:
133 case XmlNodeType.Comment:
134 case XmlNodeType.ProcessingInstruction:
135 case XmlNodeType.SignificantWhitespace:
136 case XmlNodeType.CDATA:
137 case XmlNodeType.Text:
138 case XmlNodeType.Whitespace:
139 case XmlNodeType.XmlDeclaration:
146 public abstract bool HasValue { get; }
149 public abstract bool IsEmptyElement { get; }
152 public virtual bool IsDefault {
153 get { return false; }
156 public virtual string this [int i] {
157 get { return GetAttribute (i); }
160 public virtual string this [string name] {
161 get { return GetAttribute (name); }
164 public virtual string this [string name, string namespaceURI] {
165 get { return GetAttribute (name, namespaceURI); }
168 public abstract bool IsDefault { get; }
170 public abstract string this [int i] { get; }
172 public abstract string this [string name] { get; }
174 public abstract string this [string localName, string namespaceName] { get; }
177 public abstract string LocalName { get; }
180 public virtual string Name {
182 return Prefix.Length > 0 ?
183 String.Concat (Prefix, ":", LocalName) :
188 public abstract string Name { get; }
191 public abstract string NamespaceURI { get; }
193 public abstract XmlNameTable NameTable { get; }
195 public abstract XmlNodeType NodeType { get; }
197 public abstract string Prefix { get; }
200 public virtual char QuoteChar {
204 public abstract char QuoteChar { get; }
207 public abstract ReadState ReadState { get; }
210 public virtual IXmlSchemaInfo SchemaInfo {
214 public virtual XmlReaderSettings Settings {
215 get { return settings; }
219 public abstract string Value { get; }
222 public virtual string XmlLang {
223 get { return String.Empty; }
226 public virtual XmlSpace XmlSpace {
227 get { return XmlSpace.None; }
230 public abstract string XmlLang { get; }
232 public abstract XmlSpace XmlSpace { get; }
240 public virtual void Close ()
243 throw new InvalidOperationException ("An asynchronous operation is already in progress.");
246 public abstract void Close ();
250 private static XmlNameTable PopulateNameTable (
251 XmlReaderSettings settings)
253 XmlNameTable nameTable = settings.NameTable;
254 if (nameTable == null)
255 nameTable = new NameTable ();
259 private static XmlParserContext PopulateParserContext (
260 XmlReaderSettings settings, string baseUri)
262 XmlNameTable nt = PopulateNameTable (settings);
263 return new XmlParserContext (nt,
264 new XmlNamespaceManager (nt),
275 private static XmlNodeType GetNodeType (
276 XmlReaderSettings settings)
278 ConformanceLevel level = settings != null ? settings.ConformanceLevel : ConformanceLevel.Auto;
280 level == ConformanceLevel.Fragment ?
281 XmlNodeType.Element :
282 XmlNodeType.Document;
285 public static XmlReader Create (Stream input)
287 return Create (input, null);
290 public static XmlReader Create (string inputUri)
292 return Create (inputUri, null);
295 public static XmlReader Create (TextReader input)
297 return Create (input, null);
300 public static XmlReader Create (string inputUri, XmlReaderSettings settings)
302 return Create (inputUri, settings, null);
305 public static XmlReader Create (Stream input, XmlReaderSettings settings)
307 return Create (input, settings, String.Empty);
310 public static XmlReader Create (TextReader input, XmlReaderSettings settings)
312 return Create (input, settings, String.Empty);
315 static XmlReaderSettings PopulateSettings (XmlReaderSettings src)
317 XmlReaderSettings copy;
319 copy = new XmlReaderSettings ();
328 static XmlReaderSettings PopulateSettings (XmlReader reader, XmlReaderSettings src)
330 XmlReaderSettings copy;
332 copy = new XmlReaderSettings ();
336 if (reader.Settings != null)
337 copy.Async = reader.Settings.Async;
343 public static XmlReader Create (Stream input, XmlReaderSettings settings, string baseUri)
345 settings = PopulateSettings (settings);
346 return Create (input, settings,
347 PopulateParserContext (settings, baseUri));
350 public static XmlReader Create (TextReader input, XmlReaderSettings settings, string baseUri)
352 settings = PopulateSettings (settings);
353 return Create (input, settings,
354 PopulateParserContext (settings, baseUri));
357 public static XmlReader Create (XmlReader reader, XmlReaderSettings settings)
359 settings = PopulateSettings (reader, settings);
360 XmlReader r = CreateFilteredXmlReader (reader, settings);
361 r.settings = settings;
365 public static XmlReader Create (string inputUri, XmlReaderSettings settings, XmlParserContext inputContext)
367 settings = PopulateSettings (settings);
368 bool closeInputBak = settings.CloseInput;
370 settings.CloseInput = true; // forced. See XmlReaderCommonTests.CreateFromUrlClose().
371 if (inputContext == null)
372 inputContext = PopulateParserContext (settings, inputUri);
373 XmlTextReader xtr = new XmlTextReader (false, settings.XmlResolver, inputUri, GetNodeType (settings), inputContext);
374 XmlReader ret = CreateCustomizedTextReader (xtr, settings);
377 settings.CloseInput = closeInputBak;
381 public static XmlReader Create (Stream input, XmlReaderSettings settings, XmlParserContext inputContext)
383 settings = PopulateSettings (settings);
384 if (inputContext == null)
385 inputContext = PopulateParserContext (settings, String.Empty);
386 return CreateCustomizedTextReader (new XmlTextReader (input, GetNodeType (settings), inputContext), settings);
389 public static XmlReader Create (TextReader input, XmlReaderSettings settings, XmlParserContext inputContext)
391 settings = PopulateSettings (settings);
392 if (inputContext == null)
393 inputContext = PopulateParserContext (settings, String.Empty);
394 return CreateCustomizedTextReader (new XmlTextReader (inputContext.BaseURI, input, GetNodeType (settings), inputContext), settings);
397 private static XmlReader CreateCustomizedTextReader (XmlTextReader reader, XmlReaderSettings settings)
399 reader.XmlResolver = settings.XmlResolver;
400 // Normalization is set true by default.
401 reader.Normalization = true;
402 reader.EntityHandling = EntityHandling.ExpandEntities;
404 if (settings.ProhibitDtd)
405 reader.ProhibitDtd = true;
407 if (!settings.CheckCharacters)
408 reader.CharacterChecking = false;
410 // I guess it might be changed in 2.0 RTM to set true
411 // as default, or just disappear. It goes against
412 // XmlTextReader's default usage and users will have
413 // to close input manually (that's annoying). Moreover,
414 // MS XmlTextReader consumes text input more than
415 // actually read and users can acquire those extra
416 // consumption by GetRemainder() that returns different
418 reader.CloseInput = settings.CloseInput;
420 // I would like to support it in detail later;
421 // MSDN description looks source of confusion. We don't
422 // need examples, but precise list of how it works.
423 reader.Conformance = settings.ConformanceLevel;
425 reader.AdjustLineInfoOffset (settings.LineNumberOffset,
426 settings.LinePositionOffset);
428 if (settings.NameTable != null)
429 reader.SetNameTable (settings.NameTable);
431 XmlReader r = CreateFilteredXmlReader (reader, settings);
432 r.settings = settings;
436 private static XmlReader CreateFilteredXmlReader (XmlReader reader, XmlReaderSettings settings)
438 ConformanceLevel conf = ConformanceLevel.Auto;
439 if (reader is XmlTextReader)
440 conf = ((XmlTextReader) reader).Conformance;
441 else if (reader.Settings != null)
442 conf = reader.Settings.ConformanceLevel;
444 conf = settings.ConformanceLevel;
445 if (settings.ConformanceLevel != ConformanceLevel.Auto &&
446 conf != settings.ConformanceLevel)
447 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));
448 settings.ConformanceLevel = conf;
450 reader = CreateValidatingXmlReader (reader, settings);
452 if ( settings.IgnoreComments ||
453 settings.IgnoreProcessingInstructions ||
454 settings.IgnoreWhitespace)
455 return new XmlFilterReader (reader, settings);
457 reader.settings = settings;
462 private static XmlReader CreateValidatingXmlReader (XmlReader reader, XmlReaderSettings settings)
464 XmlValidatingReader xvr = null;
465 switch (settings.ValidationType) {
466 // Auto and XDR are obsoleted in 2.0 and therefore ignored.
469 case ValidationType.DTD:
470 xvr = new XmlValidatingReader (reader);
471 xvr.XmlResolver = settings.XmlResolver;
472 xvr.ValidationType = ValidationType.DTD;
474 case ValidationType.Schema:
475 return new XmlSchemaValidatingReader (reader, settings);
478 // Actually I don't think they are treated in DTD validation though...
479 if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessIdentityConstraints) == 0)
480 throw new NotImplementedException ();
481 //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessInlineSchema) != 0)
482 // throw new NotImplementedException ();
483 //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessSchemaLocation) != 0)
484 // throw new NotImplementedException ();
485 //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ReportValidationWarnings) == 0)
486 // throw new NotImplementedException ();
488 return xvr != null ? xvr : reader;
492 public void Dispose ()
494 void IDisposable.Dispose()
500 protected virtual void Dispose (bool disposing)
502 if (ReadState != ReadState.Closed)
507 public abstract string GetAttribute (int i);
509 public abstract string GetAttribute (string name);
511 public abstract string GetAttribute (string name, string namespaceURI);
513 public static bool IsName (string str)
515 return str != null && XmlChar.IsName (str);
518 public static bool IsNameToken (string str)
520 return str != null && XmlChar.IsNmToken (str);
523 public virtual bool IsStartElement ()
525 return (MoveToContent () == XmlNodeType.Element);
528 public virtual bool IsStartElement (string name)
530 if (!IsStartElement ())
533 return (Name == name);
536 public virtual bool IsStartElement (string localname, string ns)
538 if (!IsStartElement ())
541 return (LocalName == localname && NamespaceURI == ns);
544 public abstract string LookupNamespace (string prefix);
547 public virtual void MoveToAttribute (int i)
549 if (i >= AttributeCount)
550 throw new ArgumentOutOfRangeException ();
551 MoveToFirstAttribute ();
552 for (int a = 0; a < i; a++)
553 MoveToNextAttribute ();
556 public abstract void MoveToAttribute (int i);
559 public abstract bool MoveToAttribute (string name);
561 public abstract bool MoveToAttribute (string name, string ns);
563 private bool IsContent (XmlNodeType nodeType)
566 * (non-white space text, CDATA, Element, EndElement, EntityReference, or EndEntity)
569 case XmlNodeType.Text:
571 case XmlNodeType.CDATA:
573 case XmlNodeType.Element:
575 case XmlNodeType.EndElement:
577 case XmlNodeType.EntityReference:
579 case XmlNodeType.EndEntity:
586 public virtual XmlNodeType MoveToContent ()
589 case ReadState.Initial:
590 case ReadState.Interactive:
596 if (NodeType == XmlNodeType.Attribute)
600 if (IsContent (NodeType))
604 return XmlNodeType.None;
607 public abstract bool MoveToElement ();
609 public abstract bool MoveToFirstAttribute ();
611 public abstract bool MoveToNextAttribute ();
613 public abstract bool Read ();
615 public abstract bool ReadAttributeValue ();
617 public virtual string ReadElementString ()
619 if (MoveToContent () != XmlNodeType.Element) {
620 string error = String.Format ("'{0}' is an invalid node type.",
621 NodeType.ToString ());
622 throw XmlError (error);
625 string result = String.Empty;
626 if (!IsEmptyElement) {
628 result = ReadString ();
629 if (NodeType != XmlNodeType.EndElement) {
630 string error = String.Format ("'{0}' is an invalid node type.",
631 NodeType.ToString ());
632 throw XmlError (error);
640 public virtual string ReadElementString (string name)
642 if (MoveToContent () != XmlNodeType.Element) {
643 string error = String.Format ("'{0}' is an invalid node type.",
644 NodeType.ToString ());
645 throw XmlError (error);
649 string error = String.Format ("The {0} tag from namespace {1} is expected.",
651 throw XmlError (error);
654 string result = String.Empty;
655 if (!IsEmptyElement) {
657 result = ReadString ();
658 if (NodeType != XmlNodeType.EndElement) {
659 string error = String.Format ("'{0}' is an invalid node type.",
660 NodeType.ToString ());
661 throw XmlError (error);
669 public virtual string ReadElementString (string localname, string ns)
671 if (MoveToContent () != XmlNodeType.Element) {
672 string error = String.Format ("'{0}' is an invalid node type.",
673 NodeType.ToString ());
674 throw XmlError (error);
677 if (localname != LocalName || NamespaceURI != ns) {
678 string error = String.Format ("The {0} tag from namespace {1} is expected.",
679 LocalName, NamespaceURI);
680 throw XmlError (error);
683 string result = String.Empty;
684 if (!IsEmptyElement) {
686 result = ReadString ();
687 if (NodeType != XmlNodeType.EndElement) {
688 string error = String.Format ("'{0}' is an invalid node type.",
689 NodeType.ToString ());
690 throw XmlError (error);
698 public virtual void ReadEndElement ()
700 if (MoveToContent () != XmlNodeType.EndElement) {
701 string error = String.Format ("'{0}' is an invalid node type.",
702 NodeType.ToString ());
703 throw XmlError (error);
709 public virtual string ReadInnerXml ()
711 if (ReadState != ReadState.Interactive || NodeType == XmlNodeType.EndElement)
714 if (IsEmptyElement) {
718 StringWriter sw = new StringWriter ();
719 XmlTextWriter xtw = new XmlTextWriter (sw);
720 if (NodeType == XmlNodeType.Element) {
721 int startDepth = Depth;
723 while (startDepth < Depth) {
724 if (ReadState != ReadState.Interactive)
725 throw XmlError ("Unexpected end of the XML reader.");
726 xtw.WriteNode (this, false);
728 // reader is now end element, then proceed once more.
732 xtw.WriteNode (this, false);
734 return sw.ToString ();
737 public virtual string ReadOuterXml ()
739 if (ReadState != ReadState.Interactive || NodeType == XmlNodeType.EndElement)
743 case XmlNodeType.Element:
744 case XmlNodeType.Attribute:
745 StringWriter sw = new StringWriter ();
746 XmlTextWriter xtw = new XmlTextWriter (sw);
747 xtw.WriteNode (this, false);
748 return sw.ToString ();
755 public virtual void ReadStartElement ()
757 if (MoveToContent () != XmlNodeType.Element) {
758 string error = String.Format ("'{0}' is an invalid node type.",
759 NodeType.ToString ());
760 throw XmlError (error);
766 public virtual void ReadStartElement (string name)
768 if (MoveToContent () != XmlNodeType.Element) {
769 string error = String.Format ("'{0}' is an invalid node type.",
770 NodeType.ToString ());
771 throw XmlError (error);
775 string error = String.Format ("The {0} tag from namespace {1} is expected.",
777 throw XmlError (error);
783 public virtual void ReadStartElement (string localname, string ns)
785 if (MoveToContent () != XmlNodeType.Element) {
786 string error = String.Format ("'{0}' is an invalid node type.",
787 NodeType.ToString ());
788 throw XmlError (error);
791 if (localname != LocalName || NamespaceURI != ns) {
792 string error = String.Format ("Expecting {0} tag from namespace {1}, got {2} and {3} instead",
794 LocalName, NamespaceURI);
795 throw XmlError (error);
801 public virtual string ReadString ()
803 if (readStringBuffer == null)
804 readStringBuffer = new StringBuilder ();
805 readStringBuffer.Length = 0;
812 case XmlNodeType.Element:
818 case XmlNodeType.Text:
819 case XmlNodeType.CDATA:
820 case XmlNodeType.Whitespace:
821 case XmlNodeType.SignificantWhitespace:
822 readStringBuffer.Append (Value);
828 case XmlNodeType.Text:
829 case XmlNodeType.CDATA:
830 case XmlNodeType.Whitespace:
831 case XmlNodeType.SignificantWhitespace:
834 case XmlNodeType.Text:
835 case XmlNodeType.CDATA:
836 case XmlNodeType.Whitespace:
837 case XmlNodeType.SignificantWhitespace:
838 readStringBuffer.Append (Value);
846 string ret = readStringBuffer.ToString ();
847 readStringBuffer.Length = 0;
852 public virtual Type ValueType {
853 get { return typeof (string); }
856 public virtual bool ReadToDescendant (string name)
858 if (ReadState == ReadState.Initial) {
860 if (IsStartElement (name))
863 if (NodeType != XmlNodeType.Element || IsEmptyElement)
866 for (Read (); depth < Depth; Read ())
867 if (NodeType == XmlNodeType.Element && name == Name)
872 public virtual bool ReadToDescendant (string localName, string namespaceURI)
874 if (ReadState == ReadState.Initial) {
876 if (IsStartElement (localName, namespaceURI))
879 if (NodeType != XmlNodeType.Element || IsEmptyElement)
882 for (Read (); depth < Depth; Read ())
883 if (NodeType == XmlNodeType.Element && localName == LocalName && namespaceURI == NamespaceURI)
888 public virtual bool ReadToFollowing (string name)
891 if (NodeType == XmlNodeType.Element && name == Name)
896 public virtual bool ReadToFollowing (string localName, string namespaceURI)
899 if (NodeType == XmlNodeType.Element && localName == LocalName && namespaceURI == NamespaceURI)
904 public virtual bool ReadToNextSibling (string name)
906 if (ReadState != ReadState.Interactive)
911 for (; !EOF && depth <= Depth; Skip ())
912 if (NodeType == XmlNodeType.Element && name == Name)
917 public virtual bool ReadToNextSibling (string localName, string namespaceURI)
919 if (ReadState != ReadState.Interactive)
923 for (; !EOF && depth <= Depth; Skip ())
924 if (NodeType == XmlNodeType.Element && localName == LocalName && namespaceURI == NamespaceURI)
929 public virtual XmlReader ReadSubtree ()
931 if (NodeType != XmlNodeType.Element)
932 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 ()));
933 return new SubtreeXmlReader (this);
936 private string ReadContentString ()
938 // The latter condition indicates that this XmlReader is on an attribute value
939 // (HasAttributes is to indicate it is on attribute value).
940 if (NodeType == XmlNodeType.Attribute || NodeType != XmlNodeType.Element && HasAttributes)
942 return ReadContentString (true);
945 private string ReadContentString (bool isText)
949 case XmlNodeType.Text:
950 case XmlNodeType.SignificantWhitespace:
951 case XmlNodeType.Whitespace:
952 case XmlNodeType.CDATA:
954 case XmlNodeType.Element:
955 throw new InvalidOperationException (String.Format ("Node type {0} is not supported in this operation.{1}", NodeType, GetLocation ()));
961 string value = String.Empty;
964 case XmlNodeType.Element:
967 throw XmlError ("Child element is not expected in this operation.");
968 case XmlNodeType.EndElement:
970 case XmlNodeType.Text:
971 case XmlNodeType.CDATA:
972 case XmlNodeType.SignificantWhitespace:
973 case XmlNodeType.Whitespace:
978 throw XmlError ("Unexpected end of document.");
981 string GetLocation ()
983 IXmlLineInfo li = this as IXmlLineInfo;
984 return li != null && li.HasLineInfo () ?
985 String.Format (" {0} (line {1}, column {2})", BaseURI, li.LineNumber, li.LinePosition) : String.Empty;
989 public virtual object ReadElementContentAsObject ()
991 return ReadElementContentAs (ValueType, null);
995 public virtual object ReadElementContentAsObject (string localName, string namespaceURI)
997 return ReadElementContentAs (ValueType, null, localName, namespaceURI);
1001 public virtual object ReadContentAsObject ()
1003 return ReadContentAs (ValueType, null);
1007 public virtual DateTimeOffset ReadContentAsDateTimeOffset ()
1009 return XmlConvert.ToDateTimeOffset (ReadContentString ());
1013 public virtual object ReadElementContentAs (Type returnType, IXmlNamespaceResolver namespaceResolver)
1015 bool isEmpty = IsEmptyElement;
1016 ReadStartElement ();
1017 object obj = ValueAs (isEmpty ? String.Empty : ReadContentString (false), returnType, namespaceResolver, false);
1023 public virtual object ReadElementContentAs (Type returnType, IXmlNamespaceResolver namespaceResolver, string localName, string namespaceURI)
1025 bool isEmpty = IsEmptyElement;
1026 ReadStartElement (localName, namespaceURI);
1028 return ValueAs (String.Empty, returnType, namespaceResolver, false);
1029 object obj = ReadContentAs (returnType, namespaceResolver);
1034 public virtual object ReadContentAs (Type returnType, IXmlNamespaceResolver namespaceResolver)
1036 return ValueAs (ReadContentString (), returnType, namespaceResolver, false);
1039 private object ValueAs (string text, Type type, IXmlNamespaceResolver resolver, bool isArrayItem)
1042 if (type == typeof (object))
1044 if (type.IsArray && !isArrayItem) {
1045 var elemType = type.GetElementType ();
1046 var sarr = text.Split ((string []) null, StringSplitOptions.RemoveEmptyEntries);
1047 var ret = Array.CreateInstance (elemType, sarr.Length);
1048 for (int i = 0; i < ret.Length; i++)
1049 ret.SetValue (ValueAs (sarr [i], elemType, resolver, true), i);
1053 if (type == typeof (XmlQualifiedName)) {
1054 if (resolver != null)
1055 return XmlQualifiedName.Parse (text, resolver, true);
1057 return XmlQualifiedName.Parse (text, this, true);
1059 if (type == typeof (Uri))
1060 return XmlConvert.ToUri (text);
1061 if (type == typeof (TimeSpan))
1062 return XmlConvert.ToTimeSpan (text);
1063 if (type == typeof (DateTimeOffset))
1064 return XmlConvert.ToDateTimeOffset (text);
1066 switch (Type.GetTypeCode (type)) {
1067 case TypeCode.Boolean:
1068 return XQueryConvert.StringToBoolean (text);
1069 case TypeCode.DateTime:
1070 return XQueryConvert.StringToDateTime (text);
1071 case TypeCode.Decimal:
1072 return XQueryConvert.StringToDecimal (text);
1073 case TypeCode.Double:
1074 return XQueryConvert.StringToDouble (text);
1075 case TypeCode.Int32:
1076 return XQueryConvert.StringToInt (text);
1077 case TypeCode.Int64:
1078 return XQueryConvert.StringToInteger (text);
1079 case TypeCode.Single:
1080 return XQueryConvert.StringToFloat (text);
1081 case TypeCode.String:
1084 } catch (Exception ex) {
1085 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);
1087 throw new ArgumentException (String.Format ("Specified type '{0}' is not supported.", type));
1090 public virtual bool ReadElementContentAsBoolean ()
1093 return XQueryConvert.StringToBoolean (ReadElementContentAsString ());
1094 } catch (FormatException ex) {
1095 throw XmlError ("Typed value is invalid.", ex);
1099 public virtual DateTime ReadElementContentAsDateTime ()
1102 return XQueryConvert.StringToDateTime (ReadElementContentAsString ());
1103 } catch (FormatException ex) {
1104 throw XmlError ("Typed value is invalid.", ex);
1108 public virtual decimal ReadElementContentAsDecimal ()
1111 return XQueryConvert.StringToDecimal (ReadElementContentAsString ());
1112 } catch (FormatException ex) {
1113 throw XmlError ("Typed value is invalid.", ex);
1117 public virtual double ReadElementContentAsDouble ()
1120 return XQueryConvert.StringToDouble (ReadElementContentAsString ());
1121 } catch (FormatException ex) {
1122 throw XmlError ("Typed value is invalid.", ex);
1126 public virtual float ReadElementContentAsFloat ()
1129 return XQueryConvert.StringToFloat (ReadElementContentAsString ());
1130 } catch (FormatException ex) {
1131 throw XmlError ("Typed value is invalid.", ex);
1135 public virtual int ReadElementContentAsInt ()
1138 return XQueryConvert.StringToInt (ReadElementContentAsString ());
1139 } catch (FormatException ex) {
1140 throw XmlError ("Typed value is invalid.", ex);
1144 public virtual long ReadElementContentAsLong ()
1147 return XQueryConvert.StringToInteger (ReadElementContentAsString ());
1148 } catch (FormatException ex) {
1149 throw XmlError ("Typed value is invalid.", ex);
1153 public virtual string ReadElementContentAsString ()
1155 bool isEmpty = IsEmptyElement;
1156 // unlike ReadStartElement() it rejects non-content nodes (this check is done before MoveToContent())
1157 if (NodeType != XmlNodeType.Element)
1158 throw new InvalidOperationException (String.Format ("'{0}' is an element node.", NodeType));
1159 ReadStartElement ();
1161 return String.Empty;
1162 string s = ReadContentString (false);
1167 public virtual bool ReadElementContentAsBoolean (string localName, string namespaceURI)
1170 return XQueryConvert.StringToBoolean (ReadElementContentAsString (localName, namespaceURI));
1171 } catch (FormatException ex) {
1172 throw XmlError ("Typed value is invalid.", ex);
1176 public virtual DateTime ReadElementContentAsDateTime (string localName, string namespaceURI)
1179 return XQueryConvert.StringToDateTime (ReadElementContentAsString (localName, namespaceURI));
1180 } catch (FormatException ex) {
1181 throw XmlError ("Typed value is invalid.", ex);
1185 public virtual decimal ReadElementContentAsDecimal (string localName, string namespaceURI)
1188 return XQueryConvert.StringToDecimal (ReadElementContentAsString (localName, namespaceURI));
1189 } catch (FormatException ex) {
1190 throw XmlError ("Typed value is invalid.", ex);
1194 public virtual double ReadElementContentAsDouble (string localName, string namespaceURI)
1197 return XQueryConvert.StringToDouble (ReadElementContentAsString (localName, namespaceURI));
1198 } catch (FormatException ex) {
1199 throw XmlError ("Typed value is invalid.", ex);
1203 public virtual float ReadElementContentAsFloat (string localName, string namespaceURI)
1206 return XQueryConvert.StringToFloat (ReadElementContentAsString (localName, namespaceURI));
1207 } catch (FormatException ex) {
1208 throw XmlError ("Typed value is invalid.", ex);
1212 public virtual int ReadElementContentAsInt (string localName, string namespaceURI)
1215 return XQueryConvert.StringToInt (ReadElementContentAsString (localName, namespaceURI));
1216 } catch (FormatException ex) {
1217 throw XmlError ("Typed value is invalid.", ex);
1221 public virtual long ReadElementContentAsLong (string localName, string namespaceURI)
1224 return XQueryConvert.StringToInteger (ReadElementContentAsString (localName, namespaceURI));
1225 } catch (FormatException ex) {
1226 throw XmlError ("Typed value is invalid.", ex);
1230 public virtual string ReadElementContentAsString (string localName, string namespaceURI)
1232 bool isEmpty = IsEmptyElement;
1233 // unlike ReadStartElement() it rejects non-content nodes (this check is done before MoveToContent())
1234 if (NodeType != XmlNodeType.Element)
1235 throw new InvalidOperationException (String.Format ("'{0}' is an element node.", NodeType));
1236 ReadStartElement (localName, namespaceURI);
1238 return String.Empty;
1239 string s = ReadContentString (false);
1244 public virtual bool ReadContentAsBoolean ()
1247 return XQueryConvert.StringToBoolean (ReadContentString ());
1248 } catch (FormatException ex) {
1249 throw XmlError ("Typed value is invalid.", ex);
1253 public virtual DateTime ReadContentAsDateTime ()
1256 return XQueryConvert.StringToDateTime (ReadContentString ());
1257 } catch (FormatException ex) {
1258 throw XmlError ("Typed value is invalid.", ex);
1262 public virtual decimal ReadContentAsDecimal ()
1265 return XQueryConvert.StringToDecimal (ReadContentString ());
1266 } catch (FormatException ex) {
1267 throw XmlError ("Typed value is invalid.", ex);
1271 public virtual double ReadContentAsDouble ()
1274 return XQueryConvert.StringToDouble (ReadContentString ());
1275 } catch (FormatException ex) {
1276 throw XmlError ("Typed value is invalid.", ex);
1280 public virtual float ReadContentAsFloat ()
1283 return XQueryConvert.StringToFloat (ReadContentString ());
1284 } catch (FormatException ex) {
1285 throw XmlError ("Typed value is invalid.", ex);
1289 public virtual int ReadContentAsInt ()
1292 return XQueryConvert.StringToInt (ReadContentString ());
1293 } catch (FormatException ex) {
1294 throw XmlError ("Typed value is invalid.", ex);
1298 public virtual long ReadContentAsLong ()
1301 return XQueryConvert.StringToInteger (ReadContentString ());
1302 } catch (FormatException ex) {
1303 throw XmlError ("Typed value is invalid.", ex);
1307 public virtual string ReadContentAsString ()
1309 return ReadContentString ();
1312 public virtual int ReadContentAsBase64 (
1313 byte [] buffer, int index, int count)
1316 return binary.ReadContentAsBase64 (
1317 buffer, index, count);
1320 public virtual int ReadContentAsBinHex (
1321 byte [] buffer, int index, int count)
1324 return binary.ReadContentAsBinHex (
1325 buffer, index, count);
1328 public virtual int ReadElementContentAsBase64 (
1329 byte [] buffer, int index, int count)
1332 return binary.ReadElementContentAsBase64 (
1333 buffer, index, count);
1336 public virtual int ReadElementContentAsBinHex (
1337 byte [] buffer, int index, int count)
1340 return binary.ReadElementContentAsBinHex (
1341 buffer, index, count);
1344 private void CheckSupport ()
1346 // Default implementation expects both.
1347 if (!CanReadBinaryContent || !CanReadValueChunk)
1348 throw new NotSupportedException ();
1350 binary = new XmlReaderBinarySupport (this);
1355 public virtual int ReadValueChunk (char [] buffer, int index, int count)
1357 if (!CanReadValueChunk)
1358 throw new NotSupportedException ();
1360 binary = new XmlReaderBinarySupport (this);
1361 return binary.ReadValueChunk (buffer, index, count);
1364 public abstract void ResolveEntity ();
1366 public virtual void Skip ()
1368 if (ReadState != ReadState.Interactive)
1372 if (NodeType != XmlNodeType.Element || IsEmptyElement) {
1378 while (Read () && depth < Depth)
1380 if (NodeType == XmlNodeType.EndElement)
1384 private XmlException XmlError (string message)
1386 return new XmlException (this as IXmlLineInfo, BaseURI, message);
1389 private XmlException XmlError (string message, Exception innerException)
1391 return new XmlException (this as IXmlLineInfo, BaseURI, message);
1397 #region .NET 4.5 Async Methods
1403 if (!settings.Async)
1404 throw new InvalidOperationException ("Set XmlReaderSettings.Async to true if you want to use Async Methods.");
1407 throw new InvalidOperationException ("An asynchronous operation is already in progress.");
1408 asyncRunning = true;
1412 public virtual Task<bool> ReadAsync ()
1415 return Task.Run (() => {
1419 asyncRunning = false;
1424 public virtual Task<string> GetValueAsync ()
1427 return Task.Run (() => {
1431 asyncRunning = false;
1436 public virtual Task<string> ReadInnerXmlAsync ()
1439 return Task.Run (() => {
1441 return ReadInnerXml ();
1443 asyncRunning = false;
1448 public virtual Task<string> ReadOuterXmlAsync ()
1451 return Task.Run (() => {
1453 return ReadOuterXml ();
1455 asyncRunning = false;
1460 public virtual Task<string> ReadContentAsStringAsync ()
1463 return Task.Run (() => {
1465 return ReadContentAsString ();
1467 asyncRunning = false;
1472 public virtual Task<int> ReadContentAsBase64Async (byte[] buffer, int index, int count)
1475 return Task.Run (() => {
1477 return ReadContentAsBase64 (buffer, index, count);
1479 asyncRunning = false;
1484 public virtual Task<int> ReadContentAsBinHexAsync (byte[] buffer, int index, int count)
1487 return Task.Run (() => {
1489 return ReadContentAsBinHex (buffer, index, count);
1491 asyncRunning = false;
1496 public virtual Task<int> ReadElementContentAsBase64Async (byte[] buffer, int index, int count)
1499 return Task.Run (() => {
1501 return ReadElementContentAsBase64 (buffer, index, count);
1503 asyncRunning = false;
1508 public virtual Task<int> ReadElementContentAsBinHexAsync (byte[] buffer, int index, int count)
1511 return Task.Run (() => {
1513 return ReadElementContentAsBinHex (buffer, index, count);
1515 asyncRunning = false;
1520 public virtual Task<int> ReadValueChunkAsync (char[] buffer, int index, int count)
1523 return Task.Run (() => {
1525 return ReadValueChunk (buffer, index, count);
1527 asyncRunning = false;
1532 public virtual Task<object> ReadContentAsAsync (Type returnType, IXmlNamespaceResolver namespaceResolver)
1535 return Task.Run (() => {
1537 return ReadContentAs (returnType, namespaceResolver);
1539 asyncRunning = false;
1544 public virtual Task<object> ReadContentAsObjectAsync ()
1547 return Task.Run (() => {
1549 return ReadContentAsObject ();
1551 asyncRunning = false;
1556 public virtual Task<object> ReadElementContentAsAsync (Type returnType, IXmlNamespaceResolver namespaceResolver)
1559 return Task.Run (() => {
1561 return ReadElementContentAs (returnType, namespaceResolver);
1563 asyncRunning = false;
1568 public virtual Task<object> ReadElementContentAsObjectAsync ()
1571 return Task.Run (() => {
1573 return ReadElementContentAsObject ();
1575 asyncRunning = false;
1580 public virtual Task<string> ReadElementContentAsStringAsync ()
1583 return Task.Run (() => {
1585 return ReadElementContentAsString ();
1587 asyncRunning = false;
1592 public virtual Task<XmlNodeType> MoveToContentAsync ()
1595 return Task.Run (() => {
1597 return MoveToContent ();
1599 asyncRunning = false;
1604 public virtual Task SkipAsync ()
1607 return Task.Run (() => {
1611 asyncRunning = false;