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
;
39 using System
.Xml
.Schema
; // only required for NET_2_0 (SchemaInfo)
40 using System
.Xml
.Serialization
; // only required for NET_2_0 (SchemaInfo)
41 using Mono
.Xml
.Schema
; // only required for NET_2_0
43 using Mono
.Xml
; // only required for NET_2_0
48 public abstract class XmlReader
: IDisposable
50 public abstract class XmlReader
53 private StringBuilder readStringBuffer
;
54 private XmlReaderBinarySupport binary
;
56 private XmlReaderSettings settings
;
61 protected XmlReader ()
69 public abstract int AttributeCount { get; }
71 public abstract string BaseURI { get; }
73 internal XmlReaderBinarySupport Binary
{
74 get { return binary; }
77 internal XmlReaderBinarySupport
.CharGetter BinaryCharGetter
{
78 get { return binary != null ? binary.Getter : null; }
81 binary
= new XmlReaderBinarySupport (this);
82 binary
.Getter
= value;
87 // To enable it internally in sys.xml, just insert these
88 // two lines into Read():
91 // if (Binary != null)
95 public virtual bool CanReadBinaryContent
{
99 public virtual bool CanReadValueChunk
{
100 get { return false; }
103 internal virtual bool CanReadBinaryContent
{
104 get { return false; }
107 internal virtual bool CanReadValueChunk
{
108 get { return false; }
112 public virtual bool CanResolveEntity
114 get { return false; }
117 public abstract int Depth { get; }
119 public abstract bool EOF { get; }
121 public virtual bool HasAttributes
123 get { return AttributeCount > 0; }
127 public virtual bool HasValue
{
130 case XmlNodeType
.Attribute
:
131 case XmlNodeType
.Comment
:
132 case XmlNodeType
.ProcessingInstruction
:
133 case XmlNodeType
.SignificantWhitespace
:
134 case XmlNodeType
.CDATA
:
135 case XmlNodeType
.Text
:
136 case XmlNodeType
.Whitespace
:
137 case XmlNodeType
.XmlDeclaration
:
144 public abstract bool HasValue { get; }
147 public abstract bool IsEmptyElement { get; }
150 public virtual bool IsDefault
{
151 get { return false; }
154 public virtual string this [int i
] {
155 get { return GetAttribute (i); }
158 public virtual string this [string name
] {
159 get { return GetAttribute (name); }
162 public virtual string this [string name
, string namespaceURI
] {
163 get { return GetAttribute (name, namespaceURI); }
166 public abstract bool IsDefault { get; }
168 public abstract string this [int i
] { get; }
170 public abstract string this [string name
] { get; }
172 public abstract string this [string localName
, string namespaceName
] { get; }
175 public abstract string LocalName { get; }
178 public virtual string Name
{
180 return Prefix
.Length
> 0 ?
181 String
.Concat (Prefix
, ":", LocalName
) :
186 public abstract string Name { get; }
189 public abstract string NamespaceURI { get; }
191 public abstract XmlNameTable NameTable { get; }
193 public abstract XmlNodeType NodeType { get; }
195 public abstract string Prefix { get; }
198 public virtual char QuoteChar
{
202 public abstract char QuoteChar { get; }
205 public abstract ReadState ReadState { get; }
209 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; }
239 public abstract void Close ();
242 private static XmlNameTable
PopulateNameTable (
243 XmlReaderSettings settings
)
245 XmlNameTable nameTable
= settings
.NameTable
;
246 if (nameTable
== null)
247 nameTable
= new NameTable ();
251 private static XmlParserContext
PopulateParserContext (
252 XmlReaderSettings settings
, string baseUri
)
254 XmlNameTable nt
= PopulateNameTable (settings
);
255 return new XmlParserContext (nt
,
256 new XmlNamespaceManager (nt
),
267 private static XmlNodeType
GetNodeType (
268 XmlReaderSettings settings
)
270 ConformanceLevel level
= settings
!= null ? settings
.ConformanceLevel
: ConformanceLevel
.Auto
;
272 level
== ConformanceLevel
.Fragment
?
273 XmlNodeType
.Element
:
274 XmlNodeType
.Document
;
277 public static XmlReader
Create (Stream stream
)
279 return Create (stream
, null);
282 public static XmlReader
Create (string url
)
284 return Create (url
, null);
287 public static XmlReader
Create (TextReader reader
)
289 return Create (reader
, null);
292 public static XmlReader
Create (string url
, XmlReaderSettings settings
)
294 return Create (url
, settings
, null);
297 public static XmlReader
Create (Stream stream
, XmlReaderSettings settings
)
299 return Create (stream
, settings
, String
.Empty
);
302 public static XmlReader
Create (TextReader reader
, XmlReaderSettings settings
)
304 return Create (reader
, settings
, String
.Empty
);
307 static XmlReaderSettings
PopulateSettings (XmlReaderSettings src
)
310 return new XmlReaderSettings ();
315 public static XmlReader
Create (Stream stream
, XmlReaderSettings settings
, string baseUri
)
317 settings
= PopulateSettings (settings
);
318 return Create (stream
, settings
,
319 PopulateParserContext (settings
, baseUri
));
322 public static XmlReader
Create (TextReader reader
, XmlReaderSettings settings
, string baseUri
)
324 settings
= PopulateSettings (settings
);
325 return Create (reader
, settings
,
326 PopulateParserContext (settings
, baseUri
));
329 public static XmlReader
Create (XmlReader reader
, XmlReaderSettings settings
)
331 settings
= PopulateSettings (settings
);
332 XmlReader r
= CreateFilteredXmlReader (reader
, settings
);
333 r
.settings
= settings
;
337 public static XmlReader
Create (string url
, XmlReaderSettings settings
, XmlParserContext context
)
339 settings
= PopulateSettings (settings
);
340 bool closeInputBak
= settings
.CloseInput
;
342 settings
.CloseInput
= true; // forced. See XmlReaderCommonTests.CreateFromUrlClose().
344 context
= PopulateParserContext (settings
, url
);
345 XmlTextReader xtr
= new XmlTextReader (false, settings
.XmlResolver
, url
, GetNodeType (settings
), context
);
346 XmlReader ret
= CreateCustomizedTextReader (xtr
, settings
);
349 settings
.CloseInput
= closeInputBak
;
353 public static XmlReader
Create (Stream stream
, XmlReaderSettings settings
, XmlParserContext context
)
355 settings
= PopulateSettings (settings
);
357 context
= PopulateParserContext (settings
, String
.Empty
);
358 return CreateCustomizedTextReader (new XmlTextReader (stream
, GetNodeType (settings
), context
), settings
);
361 public static XmlReader
Create (TextReader reader
, XmlReaderSettings settings
, XmlParserContext context
)
363 settings
= PopulateSettings (settings
);
365 context
= PopulateParserContext (settings
, String
.Empty
);
366 return CreateCustomizedTextReader (new XmlTextReader (context
.BaseURI
, reader
, GetNodeType (settings
), context
), settings
);
369 private static XmlReader
CreateCustomizedTextReader (XmlTextReader reader
, XmlReaderSettings settings
)
371 reader
.XmlResolver
= settings
.XmlResolver
;
372 // Normalization is set true by default.
373 reader
.Normalization
= true;
374 reader
.EntityHandling
= EntityHandling
.ExpandEntities
;
376 if (settings
.ProhibitDtd
)
377 reader
.ProhibitDtd
= true;
379 if (!settings
.CheckCharacters
)
380 reader
.CharacterChecking
= false;
382 // I guess it might be changed in 2.0 RTM to set true
383 // as default, or just disappear. It goes against
384 // XmlTextReader's default usage and users will have
385 // to close input manually (that's annoying). Moreover,
386 // MS XmlTextReader consumes text input more than
387 // actually read and users can acquire those extra
388 // consumption by GetRemainder() that returns different
390 reader
.CloseInput
= settings
.CloseInput
;
392 // I would like to support it in detail later;
393 // MSDN description looks source of confusion. We don't
394 // need examples, but precise list of how it works.
395 reader
.Conformance
= settings
.ConformanceLevel
;
397 reader
.AdjustLineInfoOffset (settings
.LineNumberOffset
,
398 settings
.LinePositionOffset
);
400 if (settings
.NameTable
!= null)
401 reader
.SetNameTable (settings
.NameTable
);
403 XmlReader r
= CreateFilteredXmlReader (reader
, settings
);
404 r
.settings
= settings
;
408 private static XmlReader
CreateFilteredXmlReader (XmlReader reader
, XmlReaderSettings settings
)
410 ConformanceLevel conf
= ConformanceLevel
.Auto
;
411 if (reader
is XmlTextReader
)
412 conf
= ((XmlTextReader
) reader
).Conformance
;
413 else if (reader
.Settings
!= null)
414 conf
= reader
.Settings
.ConformanceLevel
;
416 conf
= settings
.ConformanceLevel
;
417 if (settings
.ConformanceLevel
!= ConformanceLevel
.Auto
&&
418 conf
!= settings
.ConformanceLevel
)
419 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
));
420 settings
.ConformanceLevel
= conf
;
422 reader
= CreateValidatingXmlReader (reader
, settings
);
424 if ( settings
.IgnoreComments
||
425 settings
.IgnoreProcessingInstructions
||
426 settings
.IgnoreWhitespace
)
427 return new XmlFilterReader (reader
, settings
);
429 reader
.settings
= settings
;
434 private static XmlReader
CreateValidatingXmlReader (XmlReader reader
, XmlReaderSettings settings
)
439 XmlValidatingReader xvr
= null;
440 switch (settings
.ValidationType
) {
441 // Auto and XDR are obsoleted in 2.0 and therefore ignored.
444 case ValidationType
.DTD
:
445 xvr
= new XmlValidatingReader (reader
);
446 xvr
.XmlResolver
= settings
.XmlResolver
;
447 xvr
.ValidationType
= ValidationType
.DTD
;
449 case ValidationType
.Schema
:
450 return new XmlSchemaValidatingReader (reader
, settings
);
453 // Actually I don't think they are treated in DTD validation though...
454 if ((settings
.ValidationFlags
& XmlSchemaValidationFlags
.ProcessIdentityConstraints
) == 0)
455 throw new NotImplementedException ();
456 //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessInlineSchema) != 0)
457 // throw new NotImplementedException ();
458 //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ProcessSchemaLocation) != 0)
459 // throw new NotImplementedException ();
460 //if ((settings.ValidationFlags & XmlSchemaValidationFlags.ReportValidationWarnings) == 0)
461 // throw new NotImplementedException ();
463 return xvr
!= null ? xvr
: reader
;
467 void IDisposable
.Dispose ()
472 protected virtual void Dispose (bool disposing
)
474 if (ReadState
!= ReadState
.Closed
)
479 public abstract string GetAttribute (int i
);
481 public abstract string GetAttribute (string name
);
483 public abstract string GetAttribute (
485 string namespaceName
);
487 public static bool IsName (string s
)
489 return s
!= null && XmlChar
.IsName (s
);
492 public static bool IsNameToken (string s
)
494 return s
!= null && XmlChar
.IsNmToken (s
);
497 public virtual bool IsStartElement ()
499 return (MoveToContent () == XmlNodeType
.Element
);
502 public virtual bool IsStartElement (string name
)
504 if (!IsStartElement ())
507 return (Name
== name
);
510 public virtual bool IsStartElement (string localName
, string namespaceName
)
512 if (!IsStartElement ())
515 return (LocalName
== localName
&& NamespaceURI
== namespaceName
);
518 public abstract string LookupNamespace (string prefix
);
521 public virtual void MoveToAttribute (int i
)
523 if (i
>= AttributeCount
)
524 throw new ArgumentOutOfRangeException ();
525 MoveToFirstAttribute ();
526 for (int a
= 0; a
< i
; a
++)
527 MoveToNextAttribute ();
530 public abstract void MoveToAttribute (int i
);
533 public abstract bool MoveToAttribute (string name
);
535 public abstract bool MoveToAttribute (
537 string namespaceName
);
539 private bool IsContent (XmlNodeType nodeType
)
542 * (non-white space text, CDATA, Element, EndElement, EntityReference, or EndEntity)
545 case XmlNodeType
.Text
:
547 case XmlNodeType
.CDATA
:
549 case XmlNodeType
.Element
:
551 case XmlNodeType
.EndElement
:
553 case XmlNodeType
.EntityReference
:
555 case XmlNodeType
.EndEntity
:
562 public virtual XmlNodeType
MoveToContent ()
565 case ReadState
.Initial
:
566 case ReadState
.Interactive
:
572 if (NodeType
== XmlNodeType
.Attribute
)
576 if (IsContent (NodeType
))
580 return XmlNodeType
.None
;
583 public abstract bool MoveToElement ();
585 public abstract bool MoveToFirstAttribute ();
587 public abstract bool MoveToNextAttribute ();
589 public abstract bool Read ();
591 public abstract bool ReadAttributeValue ();
593 public virtual string ReadElementString ()
595 if (MoveToContent () != XmlNodeType
.Element
) {
596 string error
= String
.Format ("'{0}' is an invalid node type.",
597 NodeType
.ToString ());
598 throw XmlError (error
);
601 string result
= String
.Empty
;
602 if (!IsEmptyElement
) {
604 result
= ReadString ();
605 if (NodeType
!= XmlNodeType
.EndElement
) {
606 string error
= String
.Format ("'{0}' is an invalid node type.",
607 NodeType
.ToString ());
608 throw XmlError (error
);
616 public virtual string ReadElementString (string name
)
618 if (MoveToContent () != XmlNodeType
.Element
) {
619 string error
= String
.Format ("'{0}' is an invalid node type.",
620 NodeType
.ToString ());
621 throw XmlError (error
);
625 string error
= String
.Format ("The {0} tag from namespace {1} is expected.",
627 throw XmlError (error
);
630 string result
= String
.Empty
;
631 if (!IsEmptyElement
) {
633 result
= ReadString ();
634 if (NodeType
!= XmlNodeType
.EndElement
) {
635 string error
= String
.Format ("'{0}' is an invalid node type.",
636 NodeType
.ToString ());
637 throw XmlError (error
);
645 public virtual string ReadElementString (string localName
, string namespaceName
)
647 if (MoveToContent () != XmlNodeType
.Element
) {
648 string error
= String
.Format ("'{0}' is an invalid node type.",
649 NodeType
.ToString ());
650 throw XmlError (error
);
653 if (localName
!= LocalName
|| NamespaceURI
!= namespaceName
) {
654 string error
= String
.Format ("The {0} tag from namespace {1} is expected.",
655 LocalName
, NamespaceURI
);
656 throw XmlError (error
);
659 string result
= String
.Empty
;
660 if (!IsEmptyElement
) {
662 result
= ReadString ();
663 if (NodeType
!= XmlNodeType
.EndElement
) {
664 string error
= String
.Format ("'{0}' is an invalid node type.",
665 NodeType
.ToString ());
666 throw XmlError (error
);
674 public virtual void ReadEndElement ()
676 if (MoveToContent () != XmlNodeType
.EndElement
) {
677 string error
= String
.Format ("'{0}' is an invalid node type.",
678 NodeType
.ToString ());
679 throw XmlError (error
);
685 public virtual string ReadInnerXml ()
687 if (ReadState
!= ReadState
.Interactive
|| NodeType
== XmlNodeType
.EndElement
)
690 if (IsEmptyElement
) {
694 StringWriter sw
= new StringWriter ();
695 XmlTextWriter xtw
= new XmlTextWriter (sw
);
696 if (NodeType
== XmlNodeType
.Element
) {
697 int startDepth
= Depth
;
699 while (startDepth
< Depth
) {
700 if (ReadState
!= ReadState
.Interactive
)
701 throw XmlError ("Unexpected end of the XML reader.");
702 xtw
.WriteNode (this, false);
704 // reader is now end element, then proceed once more.
708 xtw
.WriteNode (this, false);
710 return sw
.ToString ();
713 public virtual string ReadOuterXml ()
715 if (ReadState
!= ReadState
.Interactive
|| NodeType
== XmlNodeType
.EndElement
)
719 case XmlNodeType
.Element
:
720 case XmlNodeType
.Attribute
:
721 StringWriter sw
= new StringWriter ();
722 XmlTextWriter xtw
= new XmlTextWriter (sw
);
723 xtw
.WriteNode (this, false);
724 return sw
.ToString ();
731 public virtual void ReadStartElement ()
733 if (MoveToContent () != XmlNodeType
.Element
) {
734 string error
= String
.Format ("'{0}' is an invalid node type.",
735 NodeType
.ToString ());
736 throw XmlError (error
);
742 public virtual void ReadStartElement (string name
)
744 if (MoveToContent () != XmlNodeType
.Element
) {
745 string error
= String
.Format ("'{0}' is an invalid node type.",
746 NodeType
.ToString ());
747 throw XmlError (error
);
751 string error
= String
.Format ("The {0} tag from namespace {1} is expected.",
753 throw XmlError (error
);
759 public virtual void ReadStartElement (string localName
, string namespaceName
)
761 if (MoveToContent () != XmlNodeType
.Element
) {
762 string error
= String
.Format ("'{0}' is an invalid node type.",
763 NodeType
.ToString ());
764 throw XmlError (error
);
767 if (localName
!= LocalName
|| NamespaceURI
!= namespaceName
) {
768 string error
= String
.Format ("Expecting {0} tag from namespace {1}, got {2} and {3} instead",
769 localName
, namespaceName
,
770 LocalName
, NamespaceURI
);
771 throw XmlError (error
);
777 public virtual string ReadString ()
779 if (readStringBuffer
== null)
780 readStringBuffer
= new StringBuilder ();
781 readStringBuffer
.Length
= 0;
788 case XmlNodeType
.Element
:
794 case XmlNodeType
.Text
:
795 case XmlNodeType
.CDATA
:
796 case XmlNodeType
.Whitespace
:
797 case XmlNodeType
.SignificantWhitespace
:
798 readStringBuffer
.Append (Value
);
804 case XmlNodeType
.Text
:
805 case XmlNodeType
.CDATA
:
806 case XmlNodeType
.Whitespace
:
807 case XmlNodeType
.SignificantWhitespace
:
810 case XmlNodeType
.Text
:
811 case XmlNodeType
.CDATA
:
812 case XmlNodeType
.Whitespace
:
813 case XmlNodeType
.SignificantWhitespace
:
814 readStringBuffer
.Append (Value
);
822 string ret
= readStringBuffer
.ToString ();
823 readStringBuffer
.Length
= 0;
828 public virtual Type ValueType
{
829 get { return typeof (string); }
832 public virtual bool ReadToDescendant (string name
)
834 if (ReadState
== ReadState
.Initial
) {
836 if (IsStartElement (name
))
839 if (NodeType
!= XmlNodeType
.Element
|| IsEmptyElement
)
842 for (Read (); depth
< Depth
; Read ())
843 if (NodeType
== XmlNodeType
.Element
&& name
== Name
)
848 public virtual bool ReadToDescendant (string localName
, string namespaceURI
)
850 if (ReadState
== ReadState
.Initial
) {
852 if (IsStartElement (localName
, namespaceURI
))
855 if (NodeType
!= XmlNodeType
.Element
|| IsEmptyElement
)
858 for (Read (); depth
< Depth
; Read ())
859 if (NodeType
== XmlNodeType
.Element
&& localName
== LocalName
&& namespaceURI
== NamespaceURI
)
864 public virtual bool ReadToFollowing (string name
)
867 if (NodeType
== XmlNodeType
.Element
&& name
== Name
)
872 public virtual bool ReadToFollowing (string localName
, string namespaceURI
)
875 if (NodeType
== XmlNodeType
.Element
&& localName
== LocalName
&& namespaceURI
== NamespaceURI
)
880 public virtual bool ReadToNextSibling (string name
)
882 if (ReadState
!= ReadState
.Interactive
)
887 for (; !EOF
&& depth
<= Depth
; Skip ())
888 if (NodeType
== XmlNodeType
.Element
&& name
== Name
)
893 public virtual bool ReadToNextSibling (string localName
, string namespaceURI
)
895 if (ReadState
!= ReadState
.Interactive
)
899 for (; !EOF
&& depth
<= Depth
; Skip ())
900 if (NodeType
== XmlNodeType
.Element
&& localName
== LocalName
&& namespaceURI
== NamespaceURI
)
905 public virtual XmlReader
ReadSubtree ()
907 if (NodeType
!= XmlNodeType
.Element
)
908 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 ()));
909 return new SubtreeXmlReader (this);
912 private string ReadContentString ()
914 // The latter condition indicates that this XmlReader is on an attribute value
915 // (HasAttributes is to indicate it is on attribute value).
916 if (NodeType
== XmlNodeType
.Attribute
|| NodeType
!= XmlNodeType
.Element
&& HasAttributes
)
918 return ReadContentString (true);
921 private string ReadContentString (bool isText
)
925 case XmlNodeType
.Text
:
926 case XmlNodeType
.SignificantWhitespace
:
927 case XmlNodeType
.Whitespace
:
928 case XmlNodeType
.CDATA
:
930 case XmlNodeType
.Element
:
931 throw new InvalidOperationException (String
.Format ("Node type {0} is not supported in this operation.{1}", NodeType
, GetLocation ()));
937 string value = String
.Empty
;
940 case XmlNodeType
.Element
:
943 throw XmlError ("Child element is not expected in this operation.");
944 case XmlNodeType
.EndElement
:
946 case XmlNodeType
.Text
:
947 case XmlNodeType
.CDATA
:
948 case XmlNodeType
.SignificantWhitespace
:
949 case XmlNodeType
.Whitespace
:
954 throw XmlError ("Unexpected end of document.");
957 string GetLocation ()
959 IXmlLineInfo li
= this as IXmlLineInfo
;
960 return li
!= null && li
.HasLineInfo () ?
961 String
.Format (" {0} (line {1}, column {2})", BaseURI
, li
.LineNumber
, li
.LinePosition
) : String
.Empty
;
965 public virtual object ReadElementContentAsObject ()
967 return ReadElementContentAs (ValueType
, null);
971 public virtual object ReadElementContentAsObject (string localName
, string namespaceURI
)
973 return ReadElementContentAs (ValueType
, null, localName
, namespaceURI
);
977 public virtual object ReadContentAsObject ()
979 return ReadContentAs (ValueType
, null);
982 public virtual object ReadElementContentAs (Type type
, IXmlNamespaceResolver resolver
)
984 bool isEmpty
= IsEmptyElement
;
986 object obj
= ValueAs (isEmpty
? String
.Empty
: ReadContentString (false), type
, resolver
, false);
992 public virtual object ReadElementContentAs (Type type
, IXmlNamespaceResolver resolver
, string localName
, string namespaceURI
)
994 bool isEmpty
= IsEmptyElement
;
995 ReadStartElement (localName
, namespaceURI
);
997 return ValueAs (String
.Empty
, type
, resolver
, false);
998 object obj
= ReadContentAs (type
, resolver
);
1003 public virtual object ReadContentAs (Type type
, IXmlNamespaceResolver resolver
)
1005 return ValueAs (ReadContentString (), type
, resolver
, false);
1008 private object ValueAs (string text
, Type type
, IXmlNamespaceResolver resolver
, bool isArrayItem
)
1011 if (type
== typeof (object))
1013 if (type
.IsArray
&& !isArrayItem
) {
1014 var elemType
= type
.GetElementType ();
1015 var sarr
= text
.Split ((string []) null, StringSplitOptions
.RemoveEmptyEntries
);
1016 var ret
= Array
.CreateInstance (elemType
, sarr
.Length
);
1017 for (int i
= 0; i
< ret
.Length
; i
++)
1018 ret
.SetValue (ValueAs (sarr
[i
], elemType
, resolver
, true), i
);
1022 if (type
== typeof (XmlQualifiedName
)) {
1023 if (resolver
!= null)
1024 return XmlQualifiedName
.Parse (text
, resolver
, true);
1026 return XmlQualifiedName
.Parse (text
, this, true);
1028 if (type
== typeof (Uri
))
1029 return XmlConvert
.ToUri (text
);
1030 if (type
== typeof (TimeSpan
))
1031 return XmlConvert
.ToTimeSpan (text
);
1032 if (type
== typeof (DateTimeOffset
))
1033 return XmlConvert
.ToDateTimeOffset (text
);
1035 switch (Type
.GetTypeCode (type
)) {
1036 case TypeCode
.Boolean
:
1037 return XQueryConvert
.StringToBoolean (text
);
1038 case TypeCode
.DateTime
:
1039 return XQueryConvert
.StringToDateTime (text
);
1040 case TypeCode
.Decimal
:
1041 return XQueryConvert
.StringToDecimal (text
);
1042 case TypeCode
.Double
:
1043 return XQueryConvert
.StringToDouble (text
);
1044 case TypeCode
.Int32
:
1045 return XQueryConvert
.StringToInt (text
);
1046 case TypeCode
.Int64
:
1047 return XQueryConvert
.StringToInteger (text
);
1048 case TypeCode
.Single
:
1049 return XQueryConvert
.StringToFloat (text
);
1050 case TypeCode
.String
:
1053 } catch (Exception ex
) {
1054 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
);
1056 throw new ArgumentException (String
.Format ("Specified type '{0}' is not supported.", type
));
1059 public virtual bool ReadElementContentAsBoolean ()
1062 return XQueryConvert
.StringToBoolean (ReadElementContentAsString ());
1063 } catch (FormatException ex
) {
1064 throw XmlError ("Typed value is invalid.", ex
);
1068 public virtual DateTime
ReadElementContentAsDateTime ()
1071 return XQueryConvert
.StringToDateTime (ReadElementContentAsString ());
1072 } catch (FormatException ex
) {
1073 throw XmlError ("Typed value is invalid.", ex
);
1077 public virtual decimal ReadElementContentAsDecimal ()
1080 return XQueryConvert
.StringToDecimal (ReadElementContentAsString ());
1081 } catch (FormatException ex
) {
1082 throw XmlError ("Typed value is invalid.", ex
);
1086 public virtual double ReadElementContentAsDouble ()
1089 return XQueryConvert
.StringToDouble (ReadElementContentAsString ());
1090 } catch (FormatException ex
) {
1091 throw XmlError ("Typed value is invalid.", ex
);
1095 public virtual float ReadElementContentAsFloat ()
1098 return XQueryConvert
.StringToFloat (ReadElementContentAsString ());
1099 } catch (FormatException ex
) {
1100 throw XmlError ("Typed value is invalid.", ex
);
1104 public virtual int ReadElementContentAsInt ()
1107 return XQueryConvert
.StringToInt (ReadElementContentAsString ());
1108 } catch (FormatException ex
) {
1109 throw XmlError ("Typed value is invalid.", ex
);
1113 public virtual long ReadElementContentAsLong ()
1116 return XQueryConvert
.StringToInteger (ReadElementContentAsString ());
1117 } catch (FormatException ex
) {
1118 throw XmlError ("Typed value is invalid.", ex
);
1122 public virtual string ReadElementContentAsString ()
1124 bool isEmpty
= IsEmptyElement
;
1125 // unlike ReadStartElement() it rejects non-content nodes (this check is done before MoveToContent())
1126 if (NodeType
!= XmlNodeType
.Element
)
1127 throw new InvalidOperationException (String
.Format ("'{0}' is an element node.", NodeType
));
1128 ReadStartElement ();
1130 return String
.Empty
;
1131 string s
= ReadContentString (false);
1136 public virtual bool ReadElementContentAsBoolean (string localName
, string namespaceURI
)
1139 return XQueryConvert
.StringToBoolean (ReadElementContentAsString (localName
, namespaceURI
));
1140 } catch (FormatException ex
) {
1141 throw XmlError ("Typed value is invalid.", ex
);
1145 public virtual DateTime
ReadElementContentAsDateTime (string localName
, string namespaceURI
)
1148 return XQueryConvert
.StringToDateTime (ReadElementContentAsString (localName
, namespaceURI
));
1149 } catch (FormatException ex
) {
1150 throw XmlError ("Typed value is invalid.", ex
);
1154 public virtual decimal ReadElementContentAsDecimal (string localName
, string namespaceURI
)
1157 return XQueryConvert
.StringToDecimal (ReadElementContentAsString (localName
, namespaceURI
));
1158 } catch (FormatException ex
) {
1159 throw XmlError ("Typed value is invalid.", ex
);
1163 public virtual double ReadElementContentAsDouble (string localName
, string namespaceURI
)
1166 return XQueryConvert
.StringToDouble (ReadElementContentAsString (localName
, namespaceURI
));
1167 } catch (FormatException ex
) {
1168 throw XmlError ("Typed value is invalid.", ex
);
1172 public virtual float ReadElementContentAsFloat (string localName
, string namespaceURI
)
1175 return XQueryConvert
.StringToFloat (ReadElementContentAsString (localName
, namespaceURI
));
1176 } catch (FormatException ex
) {
1177 throw XmlError ("Typed value is invalid.", ex
);
1181 public virtual int ReadElementContentAsInt (string localName
, string namespaceURI
)
1184 return XQueryConvert
.StringToInt (ReadElementContentAsString (localName
, namespaceURI
));
1185 } catch (FormatException ex
) {
1186 throw XmlError ("Typed value is invalid.", ex
);
1190 public virtual long ReadElementContentAsLong (string localName
, string namespaceURI
)
1193 return XQueryConvert
.StringToInteger (ReadElementContentAsString (localName
, namespaceURI
));
1194 } catch (FormatException ex
) {
1195 throw XmlError ("Typed value is invalid.", ex
);
1199 public virtual string ReadElementContentAsString (string localName
, string namespaceURI
)
1201 bool isEmpty
= IsEmptyElement
;
1202 // unlike ReadStartElement() it rejects non-content nodes (this check is done before MoveToContent())
1203 if (NodeType
!= XmlNodeType
.Element
)
1204 throw new InvalidOperationException (String
.Format ("'{0}' is an element node.", NodeType
));
1205 ReadStartElement (localName
, namespaceURI
);
1207 return String
.Empty
;
1208 string s
= ReadContentString (false);
1213 public virtual bool ReadContentAsBoolean ()
1216 return XQueryConvert
.StringToBoolean (ReadContentString ());
1217 } catch (FormatException ex
) {
1218 throw XmlError ("Typed value is invalid.", ex
);
1222 public virtual DateTime
ReadContentAsDateTime ()
1225 return XQueryConvert
.StringToDateTime (ReadContentString ());
1226 } catch (FormatException ex
) {
1227 throw XmlError ("Typed value is invalid.", ex
);
1231 public virtual decimal ReadContentAsDecimal ()
1234 return XQueryConvert
.StringToDecimal (ReadContentString ());
1235 } catch (FormatException ex
) {
1236 throw XmlError ("Typed value is invalid.", ex
);
1240 public virtual double ReadContentAsDouble ()
1243 return XQueryConvert
.StringToDouble (ReadContentString ());
1244 } catch (FormatException ex
) {
1245 throw XmlError ("Typed value is invalid.", ex
);
1249 public virtual float ReadContentAsFloat ()
1252 return XQueryConvert
.StringToFloat (ReadContentString ());
1253 } catch (FormatException ex
) {
1254 throw XmlError ("Typed value is invalid.", ex
);
1258 public virtual int ReadContentAsInt ()
1261 return XQueryConvert
.StringToInt (ReadContentString ());
1262 } catch (FormatException ex
) {
1263 throw XmlError ("Typed value is invalid.", ex
);
1267 public virtual long ReadContentAsLong ()
1270 return XQueryConvert
.StringToInteger (ReadContentString ());
1271 } catch (FormatException ex
) {
1272 throw XmlError ("Typed value is invalid.", ex
);
1276 public virtual string ReadContentAsString ()
1278 return ReadContentString ();
1281 public virtual int ReadContentAsBase64 (
1282 byte [] buffer
, int offset
, int length
)
1285 return binary
.ReadContentAsBase64 (
1286 buffer
, offset
, length
);
1289 public virtual int ReadContentAsBinHex (
1290 byte [] buffer
, int offset
, int length
)
1293 return binary
.ReadContentAsBinHex (
1294 buffer
, offset
, length
);
1297 public virtual int ReadElementContentAsBase64 (
1298 byte [] buffer
, int offset
, int length
)
1301 return binary
.ReadElementContentAsBase64 (
1302 buffer
, offset
, length
);
1305 public virtual int ReadElementContentAsBinHex (
1306 byte [] buffer
, int offset
, int length
)
1309 return binary
.ReadElementContentAsBinHex (
1310 buffer
, offset
, length
);
1313 private void CheckSupport ()
1315 // Default implementation expects both.
1316 if (!CanReadBinaryContent
|| !CanReadValueChunk
)
1317 throw new NotSupportedException ();
1319 binary
= new XmlReaderBinarySupport (this);
1325 public virtual int ReadValueChunk (
1326 char [] buffer
, int offset
, int length
)
1328 internal virtual int ReadValueChunk (
1329 char [] buffer
, int offset
, int length
)
1332 if (!CanReadValueChunk
)
1333 throw new NotSupportedException ();
1335 binary
= new XmlReaderBinarySupport (this);
1336 return binary
.ReadValueChunk (buffer
, offset
, length
);
1339 public abstract void ResolveEntity ();
1341 public virtual void Skip ()
1343 if (ReadState
!= ReadState
.Interactive
)
1347 if (NodeType
!= XmlNodeType
.Element
|| IsEmptyElement
) {
1353 while (Read () && depth
< Depth
)
1355 if (NodeType
== XmlNodeType
.EndElement
)
1359 private XmlException
XmlError (string message
)
1361 return new XmlException (this as IXmlLineInfo
, BaseURI
, message
);
1364 private XmlException
XmlError (string message
, Exception innerException
)
1366 return new XmlException (this as IXmlLineInfo
, BaseURI
, message
);