Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Xml / System / Xml / Core / XmlReader.cs
blob40379dd159eb26c7ad110e58c85cbae2bc34dbe9
2 //------------------------------------------------------------------------------
3 // <copyright file="XmlReader.cs" company="Microsoft">
4 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // </copyright>
6 // <owner current="true" primary="true">Microsoft</owner>
7 //------------------------------------------------------------------------------
9 using System.IO;
10 using System.Text;
11 using System.Security;
12 using System.Diagnostics;
13 using System.Collections;
14 using System.Globalization;
15 using System.Security.Permissions;
16 using System.Xml.Schema;
17 using System.Runtime.Versioning;
19 #if SILVERLIGHT
20 using BufferBuilder=System.Xml.BufferBuilder;
21 #else
22 using BufferBuilder = System.Text.StringBuilder;
23 #endif
25 namespace System.Xml {
27 // Represents a reader that provides fast, non-cached forward only stream access to XML data.
28 #if !SILVERLIGHT // This is used for displaying the state of the XmlReader in Watch/Locals windows in the Visual Studio during debugging
29 [DebuggerDisplay("{debuggerDisplayProxy}")]
30 #endif
31 public abstract partial class XmlReader : IDisposable {
33 static private uint IsTextualNodeBitmap = 0x6018; // 00 0110 0000 0001 1000
34 // 0 None,
35 // 0 Element,
36 // 0 Attribute,
37 // 1 Text,
38 // 1 CDATA,
39 // 0 EntityReference,
40 // 0 Entity,
41 // 0 ProcessingInstruction,
42 // 0 Comment,
43 // 0 Document,
44 // 0 DocumentType,
45 // 0 DocumentFragment,
46 // 0 Notation,
47 // 1 Whitespace,
48 // 1 SignificantWhitespace,
49 // 0 EndElement,
50 // 0 EndEntity,
51 // 0 XmlDeclaration
53 static private uint CanReadContentAsBitmap = 0x1E1BC; // 01 1110 0001 1011 1100
54 // 0 None,
55 // 0 Element,
56 // 1 Attribute,
57 // 1 Text,
58 // 1 CDATA,
59 // 1 EntityReference,
60 // 0 Entity,
61 // 1 ProcessingInstruction,
62 // 1 Comment,
63 // 0 Document,
64 // 0 DocumentType,
65 // 0 DocumentFragment,
66 // 0 Notation,
67 // 1 Whitespace,
68 // 1 SignificantWhitespace,
69 // 1 EndElement,
70 // 1 EndEntity,
71 // 0 XmlDeclaration
73 static private uint HasValueBitmap = 0x2659C; // 10 0110 0101 1001 1100
74 // 0 None,
75 // 0 Element,
76 // 1 Attribute,
77 // 1 Text,
78 // 1 CDATA,
79 // 0 EntityReference,
80 // 0 Entity,
81 // 1 ProcessingInstruction,
82 // 1 Comment,
83 // 0 Document,
84 // 1 DocumentType,
85 // 0 DocumentFragment,
86 // 0 Notation,
87 // 1 Whitespace,
88 // 1 SignificantWhitespace,
89 // 0 EndElement,
90 // 0 EndEntity,
91 // 1 XmlDeclaration
94 // Constants
96 internal const int DefaultBufferSize = 4096;
97 internal const int BiggerBufferSize = 8192;
98 internal const int MaxStreamLengthForDefaultBufferSize = 64 * 1024; // 64kB
100 internal const int AsyncBufferSize = 64 * 1024; //64KB
102 // Settings
103 public virtual XmlReaderSettings Settings {
104 get {
105 return null;
109 // Node Properties
110 // Get the type of the current node.
111 public abstract XmlNodeType NodeType { get; }
113 // Gets the name of the current node, including the namespace prefix.
114 public virtual string Name {
115 get {
116 if (Prefix.Length == 0) {
117 return LocalName;
119 else {
120 return NameTable.Add(string.Concat(Prefix, ":", LocalName));
125 // Gets the name of the current node without the namespace prefix.
126 public abstract string LocalName { get; }
128 // Gets the namespace URN (as defined in the W3C Namespace Specification) of the current namespace scope.
129 public abstract string NamespaceURI { get; }
131 // Gets the namespace prefix associated with the current node.
132 public abstract string Prefix { get; }
134 // Gets a value indicating whether
135 public virtual bool HasValue {
136 get {
137 return HasValueInternal(this.NodeType);
141 // Gets the text value of the current node.
142 public abstract string Value { get; }
144 // Gets the depth of the current node in the XML element stack.
145 public abstract int Depth { get; }
147 // Gets the base URI of the current node.
148 public abstract string BaseURI { get; }
150 // Gets a value indicating whether the current node is an empty element (for example, <MyElement/>).
151 public abstract bool IsEmptyElement { get; }
153 // Gets a value indicating whether the current node is an attribute that was generated from the default value defined
154 // in the DTD or schema.
155 public virtual bool IsDefault {
156 get {
157 return false;
161 #if !SILVERLIGHT
162 // Gets the quotation mark character used to enclose the value of an attribute node.
163 public virtual char QuoteChar {
164 get {
165 return '"';
168 #endif
170 // Gets the current xml:space scope.
171 public virtual XmlSpace XmlSpace {
172 get {
173 return XmlSpace.None;
177 // Gets the current xml:lang scope.
178 public virtual string XmlLang {
179 get {
180 return string.Empty;
184 #if !SILVERLIGHT // Removing dependency on XmlSchema
185 // returns the schema info interface of the reader
186 public virtual IXmlSchemaInfo SchemaInfo {
187 get {
188 return this as IXmlSchemaInfo;
191 #endif
193 // returns the type of the current node
194 public virtual System.Type ValueType {
195 get {
196 return typeof(string);
200 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
201 // and returns the content as the most appropriate type (by default as string). Stops at start tags and end tags.
202 public virtual object ReadContentAsObject() {
203 if (!CanReadContentAs()) {
204 throw CreateReadContentAsException("ReadContentAsObject");
206 return InternalReadContentAsString();
209 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
210 // and converts the content to a boolean. Stops at start tags and end tags.
211 public virtual bool ReadContentAsBoolean() {
212 if (!CanReadContentAs()) {
213 throw CreateReadContentAsException("ReadContentAsBoolean");
215 try {
216 return XmlConvert.ToBoolean(InternalReadContentAsString());
218 catch (FormatException e) {
219 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, this as IXmlLineInfo);
223 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
224 // and converts the content to a DateTime. Stops at start tags and end tags.
225 public virtual DateTime ReadContentAsDateTime() {
226 if (!CanReadContentAs()) {
227 throw CreateReadContentAsException("ReadContentAsDateTime");
229 try {
230 return XmlConvert.ToDateTime(InternalReadContentAsString(), XmlDateTimeSerializationMode.RoundtripKind);
232 catch (FormatException e) {
233 throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, this as IXmlLineInfo);
237 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
238 // and converts the content to a DateTimeOffset. Stops at start tags and end tags.
239 public virtual DateTimeOffset ReadContentAsDateTimeOffset() {
240 if (!CanReadContentAs()) {
241 throw CreateReadContentAsException("ReadContentAsDateTimeOffset");
243 try {
244 return XmlConvert.ToDateTimeOffset(InternalReadContentAsString());
246 catch (FormatException e) {
247 throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTimeOffset", e, this as IXmlLineInfo);
251 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
252 // and converts the content to a double. Stops at start tags and end tags.
253 public virtual double ReadContentAsDouble() {
254 if (!CanReadContentAs()) {
255 throw CreateReadContentAsException("ReadContentAsDouble");
257 try {
258 return XmlConvert.ToDouble(InternalReadContentAsString());
260 catch (FormatException e) {
261 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, this as IXmlLineInfo);
265 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
266 // and converts the content to a float. Stops at start tags and end tags.
267 public virtual float ReadContentAsFloat() {
268 if (!CanReadContentAs()) {
269 throw CreateReadContentAsException("ReadContentAsFloat");
271 try {
272 return XmlConvert.ToSingle(InternalReadContentAsString());
274 catch (FormatException e) {
275 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, this as IXmlLineInfo);
279 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
280 // and converts the content to a decimal. Stops at start tags and end tags.
281 public virtual decimal ReadContentAsDecimal() {
282 if (!CanReadContentAs()) {
283 throw CreateReadContentAsException("ReadContentAsDecimal");
285 try {
286 return XmlConvert.ToDecimal(InternalReadContentAsString());
288 catch (FormatException e) {
289 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, this as IXmlLineInfo);
293 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
294 // and converts the content to an int. Stops at start tags and end tags.
295 public virtual int ReadContentAsInt() {
296 if (!CanReadContentAs()) {
297 throw CreateReadContentAsException("ReadContentAsInt");
299 try {
300 return XmlConvert.ToInt32(InternalReadContentAsString());
302 catch (FormatException e) {
303 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int", e, this as IXmlLineInfo);
307 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
308 // and converts the content to a long. Stops at start tags and end tags.
309 public virtual long ReadContentAsLong() {
310 if (!CanReadContentAs()) {
311 throw CreateReadContentAsException("ReadContentAsLong");
313 try {
314 return XmlConvert.ToInt64(InternalReadContentAsString());
316 catch (FormatException e) {
317 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Long", e, this as IXmlLineInfo);
321 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
322 // and returns the content as a string. Stops at start tags and end tags.
323 public virtual string ReadContentAsString() {
324 if (!CanReadContentAs()) {
325 throw CreateReadContentAsException("ReadContentAsString");
327 return InternalReadContentAsString();
330 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references,
331 // and converts the content to the requested type. Stops at start tags and end tags.
332 public virtual object ReadContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver) {
333 if (!CanReadContentAs()) {
334 throw CreateReadContentAsException("ReadContentAs");
337 string strContentValue = InternalReadContentAsString();
338 if (returnType == typeof(string)) {
339 return strContentValue;
341 else {
342 try {
343 #if SILVERLIGHT
344 return XmlUntypedStringConverter.Instance.FromString(strContentValue, returnType, (namespaceResolver == null ? this as IXmlNamespaceResolver : namespaceResolver));
345 #else
346 return XmlUntypedConverter.Untyped.ChangeType(strContentValue, returnType, (namespaceResolver == null ? this as IXmlNamespaceResolver : namespaceResolver));
347 #endif
349 catch (FormatException e) {
350 throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, this as IXmlLineInfo);
352 catch (InvalidCastException e) {
353 throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, this as IXmlLineInfo);
358 // Returns the content of the current element as the most appropriate type. Moves to the node following the element's end tag.
359 public virtual object ReadElementContentAsObject() {
360 if (SetupReadElementContentAsXxx("ReadElementContentAsObject")) {
361 object value = ReadContentAsObject();
362 FinishReadElementContentAsXxx();
363 return value;
365 return string.Empty;
368 // Checks local name and namespace of the current element and returns its content as the most appropriate type. Moves to the node following the element's end tag.
369 public virtual object ReadElementContentAsObject(string localName, string namespaceURI) {
370 CheckElement(localName, namespaceURI);
371 return ReadElementContentAsObject();
374 // Returns the content of the current element as a boolean. Moves to the node following the element's end tag.
375 public virtual bool ReadElementContentAsBoolean() {
376 if (SetupReadElementContentAsXxx("ReadElementContentAsBoolean")) {
377 bool value = ReadContentAsBoolean();
378 FinishReadElementContentAsXxx();
379 return value;
381 return XmlConvert.ToBoolean(string.Empty);
384 // Checks local name and namespace of the current element and returns its content as a boolean. Moves to the node following the element's end tag.
385 public virtual bool ReadElementContentAsBoolean(string localName, string namespaceURI) {
386 CheckElement(localName, namespaceURI);
387 return ReadElementContentAsBoolean();
390 // Returns the content of the current element as a DateTime. Moves to the node following the element's end tag.
391 public virtual DateTime ReadElementContentAsDateTime() {
392 if (SetupReadElementContentAsXxx("ReadElementContentAsDateTime")) {
393 DateTime value = ReadContentAsDateTime();
394 FinishReadElementContentAsXxx();
395 return value;
397 return XmlConvert.ToDateTime(string.Empty, XmlDateTimeSerializationMode.RoundtripKind);
400 // Checks local name and namespace of the current element and returns its content as a DateTime.
401 // Moves to the node following the element's end tag.
402 public virtual DateTime ReadElementContentAsDateTime(string localName, string namespaceURI) {
403 CheckElement(localName, namespaceURI);
404 return ReadElementContentAsDateTime();
407 // Returns the content of the current element as a double. Moves to the node following the element's end tag.
408 public virtual double ReadElementContentAsDouble() {
409 if (SetupReadElementContentAsXxx("ReadElementContentAsDouble")) {
410 double value = ReadContentAsDouble();
411 FinishReadElementContentAsXxx();
412 return value;
414 return XmlConvert.ToDouble(string.Empty);
417 // Checks local name and namespace of the current element and returns its content as a double.
418 // Moves to the node following the element's end tag.
419 public virtual double ReadElementContentAsDouble(string localName, string namespaceURI) {
420 CheckElement(localName, namespaceURI);
421 return ReadElementContentAsDouble();
424 // Returns the content of the current element as a float. Moves to the node following the element's end tag.
425 public virtual float ReadElementContentAsFloat() {
426 if (SetupReadElementContentAsXxx("ReadElementContentAsFloat")) {
427 float value = ReadContentAsFloat();
428 FinishReadElementContentAsXxx();
429 return value;
431 return XmlConvert.ToSingle(string.Empty);
434 // Checks local name and namespace of the current element and returns its content as a float.
435 // Moves to the node following the element's end tag.
436 public virtual float ReadElementContentAsFloat(string localName, string namespaceURI) {
437 CheckElement(localName, namespaceURI);
438 return ReadElementContentAsFloat();
441 // Returns the content of the current element as a decimal. Moves to the node following the element's end tag.
442 public virtual decimal ReadElementContentAsDecimal() {
443 if (SetupReadElementContentAsXxx("ReadElementContentAsDecimal")) {
444 decimal value = ReadContentAsDecimal();
445 FinishReadElementContentAsXxx();
446 return value;
448 return XmlConvert.ToDecimal(string.Empty);
451 // Checks local name and namespace of the current element and returns its content as a decimal.
452 // Moves to the node following the element's end tag.
453 public virtual decimal ReadElementContentAsDecimal(string localName, string namespaceURI) {
454 CheckElement(localName, namespaceURI);
455 return ReadElementContentAsDecimal();
458 // Returns the content of the current element as an int. Moves to the node following the element's end tag.
459 public virtual int ReadElementContentAsInt() {
460 if (SetupReadElementContentAsXxx("ReadElementContentAsInt")) {
461 int value = ReadContentAsInt();
462 FinishReadElementContentAsXxx();
463 return value;
465 return XmlConvert.ToInt32(string.Empty);
468 // Checks local name and namespace of the current element and returns its content as an int.
469 // Moves to the node following the element's end tag.
470 public virtual int ReadElementContentAsInt(string localName, string namespaceURI) {
471 CheckElement(localName, namespaceURI);
472 return ReadElementContentAsInt();
475 // Returns the content of the current element as a long. Moves to the node following the element's end tag.
476 public virtual long ReadElementContentAsLong() {
477 if (SetupReadElementContentAsXxx("ReadElementContentAsLong")) {
478 long value = ReadContentAsLong();
479 FinishReadElementContentAsXxx();
480 return value;
482 return XmlConvert.ToInt64(string.Empty);
485 // Checks local name and namespace of the current element and returns its content as a long.
486 // Moves to the node following the element's end tag.
487 public virtual long ReadElementContentAsLong(string localName, string namespaceURI) {
488 CheckElement(localName, namespaceURI);
489 return ReadElementContentAsLong();
492 // Returns the content of the current element as a string. Moves to the node following the element's end tag.
493 public virtual string ReadElementContentAsString() {
494 if (SetupReadElementContentAsXxx("ReadElementContentAsString")) {
495 string value = ReadContentAsString();
496 FinishReadElementContentAsXxx();
497 return value;
499 return string.Empty;
502 // Checks local name and namespace of the current element and returns its content as a string.
503 // Moves to the node following the element's end tag.
504 public virtual string ReadElementContentAsString(string localName, string namespaceURI) {
505 CheckElement(localName, namespaceURI);
506 return ReadElementContentAsString();
509 // Returns the content of the current element as the requested type. Moves to the node following the element's end tag.
510 public virtual object ReadElementContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver) {
511 if (SetupReadElementContentAsXxx("ReadElementContentAs")) {
512 object value = ReadContentAs(returnType, namespaceResolver);
513 FinishReadElementContentAsXxx();
514 return value;
516 #if SILVERLIGHT
517 return (returnType == typeof(string)) ? string.Empty : XmlUntypedStringConverter.Instance.FromString(string.Empty, returnType, namespaceResolver);
518 #else
519 return (returnType == typeof(string)) ? string.Empty : XmlUntypedConverter.Untyped.ChangeType(string.Empty, returnType, namespaceResolver);
520 #endif
523 // Checks local name and namespace of the current element and returns its content as the requested type.
524 // Moves to the node following the element's end tag.
525 public virtual object ReadElementContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver, string localName, string namespaceURI) {
526 CheckElement(localName, namespaceURI);
527 return ReadElementContentAs(returnType, namespaceResolver);
530 // Attribute Accessors
531 // The number of attributes on the current node.
532 public abstract int AttributeCount { get; }
534 // Gets the value of the attribute with the specified Name
535 public abstract string GetAttribute(string name);
537 // Gets the value of the attribute with the LocalName and NamespaceURI
538 public abstract string GetAttribute(string name, string namespaceURI);
540 // Gets the value of the attribute with the specified index.
541 public abstract string GetAttribute(int i);
543 // Gets the value of the attribute with the specified index.
544 public virtual string this[int i] {
545 get {
546 return GetAttribute(i);
550 // Gets the value of the attribute with the specified Name.
551 public virtual string this[string name] {
552 get {
553 return GetAttribute(name);
557 // Gets the value of the attribute with the LocalName and NamespaceURI
558 public virtual string this[string name, string namespaceURI] {
559 get {
560 return GetAttribute(name, namespaceURI);
564 // Moves to the attribute with the specified Name.
565 public abstract bool MoveToAttribute(string name);
567 // Moves to the attribute with the specified LocalName and NamespaceURI.
568 public abstract bool MoveToAttribute(string name, string ns);
570 // Moves to the attribute with the specified index.
571 public virtual void MoveToAttribute(int i) {
572 if (i < 0 || i >= AttributeCount) {
573 throw new ArgumentOutOfRangeException("i");
575 MoveToElement();
576 MoveToFirstAttribute();
577 int j = 0;
578 while (j < i) {
579 MoveToNextAttribute();
580 j++;
584 // Moves to the first attribute of the current node.
585 public abstract bool MoveToFirstAttribute();
587 // Moves to the next attribute.
588 public abstract bool MoveToNextAttribute();
590 // Moves to the element that contains the current attribute node.
591 public abstract bool MoveToElement();
593 // Parses the attribute value into one or more Text and/or EntityReference node types.
595 public abstract bool ReadAttributeValue();
597 // Moving through the Stream
598 // Reads the next node from the stream.
600 public abstract bool Read();
602 // Returns true when the XmlReader is positioned at the end of the stream.
603 public abstract bool EOF { get; }
605 // Closes the stream/TextReader (if CloseInput==true), changes the ReadState to Closed, and sets all the properties back to zero/empty string.
606 public virtual void Close() { }
608 // Returns the read state of the XmlReader.
609 public abstract ReadState ReadState { get; }
611 // Skips to the end tag of the current element.
612 public virtual void Skip() {
613 if (ReadState != ReadState.Interactive) {
615 return;
618 SkipSubtree();
621 // Gets the XmlNameTable associated with the XmlReader.
622 public abstract XmlNameTable NameTable { get; }
624 // Resolves a namespace prefix in the current element's scope.
625 public abstract string LookupNamespace(string prefix);
627 // Returns true if the XmlReader can expand general entities.
628 public virtual bool CanResolveEntity {
629 get {
630 return false;
634 // Resolves the entity reference for nodes of NodeType EntityReference.
635 public abstract void ResolveEntity();
637 // Binary content access methods
638 // Returns true if the reader supports call to ReadContentAsBase64, ReadElementContentAsBase64, ReadContentAsBinHex and ReadElementContentAsBinHex.
639 public virtual bool CanReadBinaryContent {
640 get {
641 return false;
645 // Returns decoded bytes of the current base64 text content. Call this methods until it returns 0 to get all the data.
646 public virtual int ReadContentAsBase64(byte[] buffer, int index, int count) {
647 throw new NotSupportedException(Res.GetString(Res.Xml_ReadBinaryContentNotSupported, "ReadContentAsBase64"));
650 // Returns decoded bytes of the current base64 element content. Call this methods until it returns 0 to get all the data.
651 public virtual int ReadElementContentAsBase64(byte[] buffer, int index, int count) {
652 throw new NotSupportedException(Res.GetString(Res.Xml_ReadBinaryContentNotSupported, "ReadElementContentAsBase64"));
655 // Returns decoded bytes of the current binhex text content. Call this methods until it returns 0 to get all the data.
656 public virtual int ReadContentAsBinHex(byte[] buffer, int index, int count) {
657 throw new NotSupportedException(Res.GetString(Res.Xml_ReadBinaryContentNotSupported, "ReadContentAsBinHex"));
660 // Returns decoded bytes of the current binhex element content. Call this methods until it returns 0 to get all the data.
661 public virtual int ReadElementContentAsBinHex(byte[] buffer, int index, int count) {
662 throw new NotSupportedException(Res.GetString(Res.Xml_ReadBinaryContentNotSupported, "ReadElementContentAsBinHex"));
665 // Text streaming methods
667 // Returns true if the XmlReader supports calls to ReadValueChunk.
668 public virtual bool CanReadValueChunk {
669 get {
670 return false;
674 // Returns a chunk of the value of the current node. Call this method in a loop to get all the data.
675 // Use this method to get a streaming access to the value of the current node.
676 public virtual int ReadValueChunk(char[] buffer, int index, int count) {
677 throw new NotSupportedException(Res.GetString(Res.Xml_ReadValueChunkNotSupported));
680 #if !SILVERLIGHT
681 // Virtual helper methods
682 // Reads the contents of an element as a string. Stops of comments, PIs or entity references.
683 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
684 public virtual string ReadString() {
685 if (this.ReadState != ReadState.Interactive) {
686 return string.Empty;
688 this.MoveToElement();
689 if (this.NodeType == XmlNodeType.Element) {
690 if (this.IsEmptyElement) {
691 return string.Empty;
693 else if (!this.Read()) {
694 throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
696 if (this.NodeType == XmlNodeType.EndElement) {
697 return string.Empty;
700 string result = string.Empty;
701 while (IsTextualNode(this.NodeType)) {
702 result += this.Value;
703 if (!this.Read()) {
704 break;
707 return result;
709 #endif
711 // Checks whether the current node is a content (non-whitespace text, CDATA, Element, EndElement, EntityReference
712 // or EndEntity) node. If the node is not a content node, then the method skips ahead to the next content node or
713 // end of file. Skips over nodes of type ProcessingInstruction, DocumentType, Comment, Whitespace and SignificantWhitespace.
714 public virtual XmlNodeType MoveToContent() {
715 do {
716 switch (this.NodeType) {
717 case XmlNodeType.Attribute:
718 MoveToElement();
719 goto case XmlNodeType.Element;
720 case XmlNodeType.Element:
721 case XmlNodeType.EndElement:
722 case XmlNodeType.CDATA:
723 case XmlNodeType.Text:
724 case XmlNodeType.EntityReference:
725 case XmlNodeType.EndEntity:
726 return this.NodeType;
728 } while (Read());
729 return this.NodeType;
732 // Checks that the current node is an element and advances the reader to the next node.
733 public virtual void ReadStartElement() {
734 if (MoveToContent() != XmlNodeType.Element) {
735 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo);
737 Read();
740 // Checks that the current content node is an element with the given Name and advances the reader to the next node.
741 public virtual void ReadStartElement(string name) {
742 if (MoveToContent() != XmlNodeType.Element) {
743 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo);
745 if (this.Name == name) {
746 Read();
748 else {
749 throw new XmlException(Res.Xml_ElementNotFound, name, this as IXmlLineInfo);
753 // Checks that the current content node is an element with the given LocalName and NamespaceURI
754 // and advances the reader to the next node.
755 public virtual void ReadStartElement(string localname, string ns) {
756 if (MoveToContent() != XmlNodeType.Element) {
757 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo);
759 if (this.LocalName == localname && this.NamespaceURI == ns) {
760 Read();
762 else {
763 throw new XmlException(Res.Xml_ElementNotFoundNs, new string[2] { localname, ns }, this as IXmlLineInfo);
767 #if !SILVERLIGHT
768 // Reads a text-only element.
769 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
770 public virtual string ReadElementString() {
771 string result = string.Empty;
773 if (MoveToContent() != XmlNodeType.Element) {
774 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo);
776 if (!this.IsEmptyElement) {
777 Read();
778 result = ReadString();
779 if (this.NodeType != XmlNodeType.EndElement) {
780 throw new XmlException(Res.Xml_UnexpectedNodeInSimpleContent, new string[] { this.NodeType.ToString(), "ReadElementString" }, this as IXmlLineInfo);
782 Read();
784 else {
785 Read();
787 return result;
790 // Checks that the Name property of the element found matches the given string before reading a text-only element.
791 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
792 public virtual string ReadElementString(string name) {
793 string result = string.Empty;
795 if (MoveToContent() != XmlNodeType.Element) {
796 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo);
798 if (this.Name != name) {
799 throw new XmlException(Res.Xml_ElementNotFound, name, this as IXmlLineInfo);
802 if (!this.IsEmptyElement) {
803 //Read();
804 result = ReadString();
805 if (this.NodeType != XmlNodeType.EndElement) {
806 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo);
808 Read();
810 else {
811 Read();
813 return result;
816 // Checks that the LocalName and NamespaceURI properties of the element found matches the given strings
817 // before reading a text-only element.
818 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
819 public virtual string ReadElementString(string localname, string ns) {
820 string result = string.Empty;
821 if (MoveToContent() != XmlNodeType.Element) {
822 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo);
824 if (this.LocalName != localname || this.NamespaceURI != ns) {
825 throw new XmlException(Res.Xml_ElementNotFoundNs, new string[2] { localname, ns }, this as IXmlLineInfo);
828 if (!this.IsEmptyElement) {
829 //Read();
830 result = ReadString();
831 if (this.NodeType != XmlNodeType.EndElement) {
832 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo);
834 Read();
836 else {
837 Read();
840 return result;
842 #endif
843 // Checks that the current content node is an end tag and advances the reader to the next node.
844 public virtual void ReadEndElement() {
845 if (MoveToContent() != XmlNodeType.EndElement) {
846 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo);
848 Read();
851 // Calls MoveToContent and tests if the current content node is a start tag or empty element tag (XmlNodeType.Element).
852 public virtual bool IsStartElement() {
853 return MoveToContent() == XmlNodeType.Element;
856 // Calls MoveToContentand tests if the current content node is a start tag or empty element tag (XmlNodeType.Element) and if the
857 // Name property of the element found matches the given argument.
858 public virtual bool IsStartElement(string name) {
859 return (MoveToContent() == XmlNodeType.Element) &&
860 (this.Name == name);
863 // Calls MoveToContent and tests if the current content node is a start tag or empty element tag (XmlNodeType.Element) and if
864 // the LocalName and NamespaceURI properties of the element found match the given strings.
865 public virtual bool IsStartElement(string localname, string ns) {
866 return (MoveToContent() == XmlNodeType.Element) &&
867 (this.LocalName == localname && this.NamespaceURI == ns);
870 // Reads to the following element with the given Name.
871 public virtual bool ReadToFollowing(string name) {
872 if (name == null || name.Length == 0) {
873 throw XmlConvert.CreateInvalidNameArgumentException(name, "name");
875 // atomize name
876 name = NameTable.Add(name);
878 // find following element with that name
879 while (Read()) {
880 if (NodeType == XmlNodeType.Element && Ref.Equal(name, Name)) {
881 return true;
884 return false;
887 // Reads to the following element with the given LocalName and NamespaceURI.
888 public virtual bool ReadToFollowing(string localName, string namespaceURI) {
889 if (localName == null || localName.Length == 0) {
890 throw XmlConvert.CreateInvalidNameArgumentException(localName, "localName");
892 if (namespaceURI == null) {
893 throw new ArgumentNullException("namespaceURI");
896 // atomize local name and namespace
897 localName = NameTable.Add(localName);
898 namespaceURI = NameTable.Add(namespaceURI);
900 // find following element with that name
901 while (Read()) {
902 if (NodeType == XmlNodeType.Element && Ref.Equal(localName, LocalName) && Ref.Equal(namespaceURI, NamespaceURI)) {
903 return true;
906 return false;
909 // Reads to the first descendant of the current element with the given Name.
910 public virtual bool ReadToDescendant(string name) {
911 if (name == null || name.Length == 0) {
912 throw XmlConvert.CreateInvalidNameArgumentException(name, "name");
914 // save the element or root depth
915 int parentDepth = Depth;
916 if (NodeType != XmlNodeType.Element) {
917 // adjust the depth if we are on root node
918 if (ReadState == ReadState.Initial) {
919 Debug.Assert(parentDepth == 0);
920 parentDepth--;
922 else {
923 return false;
926 else if (IsEmptyElement) {
927 return false;
930 // atomize name
931 name = NameTable.Add(name);
933 // find the descendant
934 while (Read() && Depth > parentDepth) {
935 if (NodeType == XmlNodeType.Element && Ref.Equal(name, Name)) {
936 return true;
939 Debug.Assert(NodeType == XmlNodeType.EndElement || NodeType == XmlNodeType.None || ReadState == ReadState.Error);
940 return false;
943 // Reads to the first descendant of the current element with the given LocalName and NamespaceURI.
944 public virtual bool ReadToDescendant(string localName, string namespaceURI) {
945 if (localName == null || localName.Length == 0) {
946 throw XmlConvert.CreateInvalidNameArgumentException(localName, "localName");
948 if (namespaceURI == null) {
949 throw new ArgumentNullException("namespaceURI");
951 // save the element or root depth
952 int parentDepth = Depth;
953 if (NodeType != XmlNodeType.Element) {
954 // adjust the depth if we are on root node
955 if (ReadState == ReadState.Initial) {
956 Debug.Assert(parentDepth == 0);
957 parentDepth--;
959 else {
960 return false;
963 else if (IsEmptyElement) {
964 return false;
967 // atomize local name and namespace
968 localName = NameTable.Add(localName);
969 namespaceURI = NameTable.Add(namespaceURI);
971 // find the descendant
972 while (Read() && Depth > parentDepth) {
973 if (NodeType == XmlNodeType.Element && Ref.Equal(localName, LocalName) && Ref.Equal(namespaceURI, NamespaceURI)) {
974 return true;
977 Debug.Assert(NodeType == XmlNodeType.EndElement);
978 return false;
981 // Reads to the next sibling of the current element with the given Name.
982 public virtual bool ReadToNextSibling(string name) {
983 if (name == null || name.Length == 0) {
984 throw XmlConvert.CreateInvalidNameArgumentException(name, "name");
987 // atomize name
988 name = NameTable.Add(name);
990 // find the next sibling
991 XmlNodeType nt;
992 do {
993 if (!SkipSubtree()) {
994 break;
996 nt = NodeType;
997 if (nt == XmlNodeType.Element && Ref.Equal(name, Name)) {
998 return true;
1000 } while (nt != XmlNodeType.EndElement && !EOF);
1001 return false;
1004 // Reads to the next sibling of the current element with the given LocalName and NamespaceURI.
1005 public virtual bool ReadToNextSibling(string localName, string namespaceURI) {
1006 if (localName == null || localName.Length == 0) {
1007 throw XmlConvert.CreateInvalidNameArgumentException(localName, "localName");
1009 if (namespaceURI == null) {
1010 throw new ArgumentNullException("namespaceURI");
1013 // atomize local name and namespace
1014 localName = NameTable.Add(localName);
1015 namespaceURI = NameTable.Add(namespaceURI);
1017 // find the next sibling
1018 XmlNodeType nt;
1019 do {
1020 if (!SkipSubtree()) {
1021 break;
1023 nt = NodeType;
1024 if (nt == XmlNodeType.Element && Ref.Equal(localName, LocalName) && Ref.Equal(namespaceURI, NamespaceURI)) {
1025 return true;
1027 } while (nt != XmlNodeType.EndElement && !EOF);
1028 return false;
1031 // Returns true if the given argument is a valid Name.
1032 public static bool IsName(string str) {
1033 if (str == null) {
1034 throw new NullReferenceException();
1036 return ValidateNames.IsNameNoNamespaces(str);
1039 // Returns true if the given argument is a valid NmToken.
1040 public static bool IsNameToken(string str) {
1041 if (str == null) {
1042 throw new NullReferenceException();
1044 return ValidateNames.IsNmtokenNoNamespaces(str);
1047 // Returns the inner content (including markup) of an element or attribute as a string.
1048 public virtual string ReadInnerXml() {
1049 if (ReadState != ReadState.Interactive) {
1050 return string.Empty;
1052 if ((this.NodeType != XmlNodeType.Attribute) && (this.NodeType != XmlNodeType.Element)) {
1053 Read();
1054 return string.Empty;
1057 StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
1058 XmlWriter xtw = CreateWriterForInnerOuterXml(sw);
1060 try {
1061 if (this.NodeType == XmlNodeType.Attribute) {
1062 #if !SILVERLIGHT // Removing dependency on XmlTextWriter
1063 ((XmlTextWriter)xtw).QuoteChar = this.QuoteChar;
1064 #endif
1065 WriteAttributeValue(xtw);
1067 if (this.NodeType == XmlNodeType.Element) {
1068 this.WriteNode(xtw, false);
1071 finally {
1072 xtw.Close();
1074 return sw.ToString();
1077 // Writes the content (inner XML) of the current node into the provided XmlWriter.
1078 private void WriteNode(XmlWriter xtw, bool defattr) {
1079 #if !SILVERLIGHT
1080 Debug.Assert(xtw is XmlTextWriter);
1081 #endif
1082 int d = this.NodeType == XmlNodeType.None ? -1 : this.Depth;
1083 while (this.Read() && (d < this.Depth)) {
1084 switch (this.NodeType) {
1085 case XmlNodeType.Element:
1086 xtw.WriteStartElement(this.Prefix, this.LocalName, this.NamespaceURI);
1087 #if !SILVERLIGHT // Removing dependency on XmlTextWriter
1088 ((XmlTextWriter)xtw).QuoteChar = this.QuoteChar;
1089 #endif
1090 xtw.WriteAttributes(this, defattr);
1091 if (this.IsEmptyElement) {
1092 xtw.WriteEndElement();
1094 break;
1095 case XmlNodeType.Text:
1096 xtw.WriteString(this.Value);
1097 break;
1098 case XmlNodeType.Whitespace:
1099 case XmlNodeType.SignificantWhitespace:
1100 xtw.WriteWhitespace(this.Value);
1101 break;
1102 case XmlNodeType.CDATA:
1103 xtw.WriteCData(this.Value);
1104 break;
1105 case XmlNodeType.EntityReference:
1106 xtw.WriteEntityRef(this.Name);
1107 break;
1108 case XmlNodeType.XmlDeclaration:
1109 case XmlNodeType.ProcessingInstruction:
1110 xtw.WriteProcessingInstruction(this.Name, this.Value);
1111 break;
1112 case XmlNodeType.DocumentType:
1113 xtw.WriteDocType(this.Name, this.GetAttribute("PUBLIC"), this.GetAttribute("SYSTEM"), this.Value);
1114 break;
1115 case XmlNodeType.Comment:
1116 xtw.WriteComment(this.Value);
1117 break;
1118 case XmlNodeType.EndElement:
1119 xtw.WriteFullEndElement();
1120 break;
1123 if (d == this.Depth && this.NodeType == XmlNodeType.EndElement) {
1124 Read();
1128 // Writes the attribute into the provided XmlWriter.
1129 private void WriteAttributeValue(XmlWriter xtw) {
1130 string attrName = this.Name;
1131 while (ReadAttributeValue()) {
1132 if (this.NodeType == XmlNodeType.EntityReference) {
1133 xtw.WriteEntityRef(this.Name);
1135 else {
1136 xtw.WriteString(this.Value);
1139 this.MoveToAttribute(attrName);
1142 // Returns the current element and its descendants or an attribute as a string.
1143 public virtual string ReadOuterXml() {
1144 if (ReadState != ReadState.Interactive) {
1145 return string.Empty;
1147 if ((this.NodeType != XmlNodeType.Attribute) && (this.NodeType != XmlNodeType.Element)) {
1148 Read();
1149 return string.Empty;
1152 StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
1153 XmlWriter xtw = CreateWriterForInnerOuterXml(sw);
1155 try {
1156 if (this.NodeType == XmlNodeType.Attribute) {
1157 xtw.WriteStartAttribute(this.Prefix, this.LocalName, this.NamespaceURI);
1158 WriteAttributeValue(xtw);
1159 xtw.WriteEndAttribute();
1161 else {
1162 xtw.WriteNode(this, false);
1165 finally {
1166 xtw.Close();
1168 return sw.ToString();
1171 private XmlWriter CreateWriterForInnerOuterXml(StringWriter sw) {
1172 #if SILVERLIGHT // Removing dependency on XmlTextWriter
1173 XmlWriterSettings writerSettings = new XmlWriterSettings();
1174 writerSettings.OmitXmlDeclaration = true;
1175 writerSettings.ConformanceLevel = ConformanceLevel.Fragment;
1176 writerSettings.CheckCharacters = false;
1177 writerSettings.NewLineHandling = NewLineHandling.None;
1178 XmlWriter w = XmlWriter.Create(sw, writerSettings);
1179 #else
1180 XmlTextWriter w = new XmlTextWriter(sw);
1181 // This is a V1 hack; we can put a custom implementation of ReadOuterXml on XmlTextReader/XmlValidatingReader
1182 SetNamespacesFlag(w);
1183 #endif
1184 return w;
1187 #if !SILVERLIGHT // Removing dependency on XmlTextWriter
1188 void SetNamespacesFlag(XmlTextWriter xtw) {
1189 XmlTextReader tr = this as XmlTextReader;
1190 if (tr != null) {
1191 xtw.Namespaces = tr.Namespaces;
1193 else {
1194 #pragma warning disable 618
1195 XmlValidatingReader vr = this as XmlValidatingReader;
1196 if (vr != null) {
1197 xtw.Namespaces = vr.Namespaces;
1200 #pragma warning restore 618
1202 #endif
1204 // Returns an XmlReader that will read only the current element and its descendants and then go to EOF state.
1205 public virtual XmlReader ReadSubtree() {
1206 if (NodeType != XmlNodeType.Element) {
1207 throw new InvalidOperationException(Res.GetString(Res.Xml_ReadSubtreeNotOnElement));
1209 return new XmlSubtreeReader(this);
1212 // Returns true when the current node has any attributes.
1213 public virtual bool HasAttributes {
1214 get {
1215 return AttributeCount > 0;
1220 // IDisposable interface
1222 public void Dispose() {
1223 Dispose(true);
1226 protected virtual void Dispose(bool disposing) { //the boolean flag may be used by subclasses to differentiate between disposing and finalizing
1227 if (disposing && ReadState != ReadState.Closed) {
1228 Close();
1233 // Internal methods
1235 // Validation support
1236 #if !SILVERLIGHT
1237 internal virtual XmlNamespaceManager NamespaceManager {
1238 get {
1239 return null;
1242 #endif
1244 static internal bool IsTextualNode(XmlNodeType nodeType) {
1245 #if DEBUG
1246 // This code verifies IsTextualNodeBitmap mapping of XmlNodeType to a bool specifying
1247 // whether the node is 'textual' = Text, CDATA, Whitespace or SignificantWhitespace.
1248 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.None)));
1249 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.Element)));
1250 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.Attribute)));
1251 Debug.Assert(0 != (IsTextualNodeBitmap & (1 << (int)XmlNodeType.Text)));
1252 Debug.Assert(0 != (IsTextualNodeBitmap & (1 << (int)XmlNodeType.CDATA)));
1253 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.EntityReference)));
1254 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.Entity)));
1255 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.ProcessingInstruction)));
1256 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.Comment)));
1257 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.Document)));
1258 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.DocumentType)));
1259 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.DocumentFragment)));
1260 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.Notation)));
1261 Debug.Assert(0 != (IsTextualNodeBitmap & (1 << (int)XmlNodeType.Whitespace)));
1262 Debug.Assert(0 != (IsTextualNodeBitmap & (1 << (int)XmlNodeType.SignificantWhitespace)));
1263 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.EndElement)));
1264 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.EndEntity)));
1265 Debug.Assert(0 == (IsTextualNodeBitmap & (1 << (int)XmlNodeType.XmlDeclaration)));
1266 #endif
1267 return 0 != (IsTextualNodeBitmap & (1 << (int)nodeType));
1270 static internal bool CanReadContentAs(XmlNodeType nodeType) {
1271 #if DEBUG
1272 // This code verifies IsTextualNodeBitmap mapping of XmlNodeType to a bool specifying
1273 // whether ReadContentAsXxx calls are allowed on his node type
1274 Debug.Assert(0 == (CanReadContentAsBitmap & (1 << (int)XmlNodeType.None)));
1275 Debug.Assert(0 == (CanReadContentAsBitmap & (1 << (int)XmlNodeType.Element)));
1276 Debug.Assert(0 != (CanReadContentAsBitmap & (1 << (int)XmlNodeType.Attribute)));
1277 Debug.Assert(0 != (CanReadContentAsBitmap & (1 << (int)XmlNodeType.Text)));
1278 Debug.Assert(0 != (CanReadContentAsBitmap & (1 << (int)XmlNodeType.CDATA)));
1279 Debug.Assert(0 != (CanReadContentAsBitmap & (1 << (int)XmlNodeType.EntityReference)));
1280 Debug.Assert(0 == (CanReadContentAsBitmap & (1 << (int)XmlNodeType.Entity)));
1281 Debug.Assert(0 != (CanReadContentAsBitmap & (1 << (int)XmlNodeType.ProcessingInstruction)));
1282 Debug.Assert(0 != (CanReadContentAsBitmap & (1 << (int)XmlNodeType.Comment)));
1283 Debug.Assert(0 == (CanReadContentAsBitmap & (1 << (int)XmlNodeType.Document)));
1284 Debug.Assert(0 == (CanReadContentAsBitmap & (1 << (int)XmlNodeType.DocumentType)));
1285 Debug.Assert(0 == (CanReadContentAsBitmap & (1 << (int)XmlNodeType.DocumentFragment)));
1286 Debug.Assert(0 == (CanReadContentAsBitmap & (1 << (int)XmlNodeType.Notation)));
1287 Debug.Assert(0 != (CanReadContentAsBitmap & (1 << (int)XmlNodeType.Whitespace)));
1288 Debug.Assert(0 != (CanReadContentAsBitmap & (1 << (int)XmlNodeType.SignificantWhitespace)));
1289 Debug.Assert(0 != (CanReadContentAsBitmap & (1 << (int)XmlNodeType.EndElement)));
1290 Debug.Assert(0 != (CanReadContentAsBitmap & (1 << (int)XmlNodeType.EndEntity)));
1291 Debug.Assert(0 == (CanReadContentAsBitmap & (1 << (int)XmlNodeType.XmlDeclaration)));
1292 #endif
1293 return 0 != (CanReadContentAsBitmap & (1 << (int)nodeType));
1296 static internal bool HasValueInternal(XmlNodeType nodeType) {
1297 #if DEBUG
1298 // This code verifies HasValueBitmap mapping of XmlNodeType to a bool specifying
1299 // whether the node can have a non-empty Value
1300 Debug.Assert(0 == (HasValueBitmap & (1 << (int)XmlNodeType.None)));
1301 Debug.Assert(0 == (HasValueBitmap & (1 << (int)XmlNodeType.Element)));
1302 Debug.Assert(0 != (HasValueBitmap & (1 << (int)XmlNodeType.Attribute)));
1303 Debug.Assert(0 != (HasValueBitmap & (1 << (int)XmlNodeType.Text)));
1304 Debug.Assert(0 != (HasValueBitmap & (1 << (int)XmlNodeType.CDATA)));
1305 Debug.Assert(0 == (HasValueBitmap & (1 << (int)XmlNodeType.EntityReference)));
1306 Debug.Assert(0 == (HasValueBitmap & (1 << (int)XmlNodeType.Entity)));
1307 Debug.Assert(0 != (HasValueBitmap & (1 << (int)XmlNodeType.ProcessingInstruction)));
1308 Debug.Assert(0 != (HasValueBitmap & (1 << (int)XmlNodeType.Comment)));
1309 Debug.Assert(0 == (HasValueBitmap & (1 << (int)XmlNodeType.Document)));
1310 Debug.Assert(0 != (HasValueBitmap & (1 << (int)XmlNodeType.DocumentType)));
1311 Debug.Assert(0 == (HasValueBitmap & (1 << (int)XmlNodeType.DocumentFragment)));
1312 Debug.Assert(0 == (HasValueBitmap & (1 << (int)XmlNodeType.Notation)));
1313 Debug.Assert(0 != (HasValueBitmap & (1 << (int)XmlNodeType.Whitespace)));
1314 Debug.Assert(0 != (HasValueBitmap & (1 << (int)XmlNodeType.SignificantWhitespace)));
1315 Debug.Assert(0 == (HasValueBitmap & (1 << (int)XmlNodeType.EndElement)));
1316 Debug.Assert(0 == (HasValueBitmap & (1 << (int)XmlNodeType.EndEntity)));
1317 Debug.Assert(0 != (HasValueBitmap & (1 << (int)XmlNodeType.XmlDeclaration)));
1318 #endif
1319 return 0 != (HasValueBitmap & (1 << (int)nodeType));
1323 // Private methods
1325 //SkipSubTree is called whenever validation of the skipped subtree is required on a reader with XsdValidation
1326 private bool SkipSubtree() {
1327 MoveToElement();
1328 if (NodeType == XmlNodeType.Element && !IsEmptyElement) {
1329 int depth = Depth;
1331 while (Read() && depth < Depth) {
1332 // Nothing, just read on
1335 // consume end tag
1336 if (NodeType == XmlNodeType.EndElement)
1337 return Read();
1339 else {
1340 return Read();
1343 return false;
1346 internal void CheckElement(string localName, string namespaceURI) {
1347 if (localName == null || localName.Length == 0) {
1348 throw XmlConvert.CreateInvalidNameArgumentException(localName, "localName");
1350 if (namespaceURI == null) {
1351 throw new ArgumentNullException("namespaceURI");
1353 if (NodeType != XmlNodeType.Element) {
1354 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo);
1356 if (LocalName != localName || NamespaceURI != namespaceURI) {
1357 throw new XmlException(Res.Xml_ElementNotFoundNs, new string[2] { localName, namespaceURI }, this as IXmlLineInfo);
1361 internal Exception CreateReadContentAsException(string methodName) {
1362 return CreateReadContentAsException(methodName, NodeType, this as IXmlLineInfo);
1365 internal Exception CreateReadElementContentAsException(string methodName) {
1366 return CreateReadElementContentAsException(methodName, NodeType, this as IXmlLineInfo);
1369 internal bool CanReadContentAs() {
1370 return CanReadContentAs(this.NodeType);
1373 static internal Exception CreateReadContentAsException(string methodName, XmlNodeType nodeType, IXmlLineInfo lineInfo) {
1374 return new InvalidOperationException(AddLineInfo(Res.GetString(Res.Xml_InvalidReadContentAs, new string[] { methodName, nodeType.ToString() }), lineInfo));
1377 static internal Exception CreateReadElementContentAsException(string methodName, XmlNodeType nodeType, IXmlLineInfo lineInfo) {
1378 return new InvalidOperationException(AddLineInfo(Res.GetString(Res.Xml_InvalidReadElementContentAs, new string[] { methodName, nodeType.ToString() }), lineInfo));
1381 static string AddLineInfo(string message, IXmlLineInfo lineInfo) {
1382 if (lineInfo != null) {
1383 string[] lineArgs = new string[2];
1384 lineArgs[0] = lineInfo.LineNumber.ToString(CultureInfo.InvariantCulture);
1385 lineArgs[1] = lineInfo.LinePosition.ToString(CultureInfo.InvariantCulture);
1386 message += " " + Res.GetString(Res.Xml_ErrorPosition, lineArgs);
1388 return message;
1391 internal string InternalReadContentAsString() {
1392 string value = string.Empty;
1393 BufferBuilder sb = null;
1394 do {
1395 switch (this.NodeType) {
1396 case XmlNodeType.Attribute:
1397 return this.Value;
1398 case XmlNodeType.Text:
1399 case XmlNodeType.Whitespace:
1400 case XmlNodeType.SignificantWhitespace:
1401 case XmlNodeType.CDATA:
1402 // merge text content
1403 if (value.Length == 0) {
1404 value = this.Value;
1406 else {
1407 if (sb == null) {
1408 sb = new BufferBuilder();
1409 sb.Append(value);
1411 sb.Append(this.Value);
1413 break;
1414 case XmlNodeType.ProcessingInstruction:
1415 case XmlNodeType.Comment:
1416 case XmlNodeType.EndEntity:
1417 // skip comments, pis and end entity nodes
1418 break;
1419 case XmlNodeType.EntityReference:
1420 if (this.CanResolveEntity) {
1421 this.ResolveEntity();
1422 break;
1424 goto default;
1425 case XmlNodeType.EndElement:
1426 default:
1427 goto ReturnContent;
1429 } while ((this.AttributeCount != 0) ? this.ReadAttributeValue() : this.Read());
1431 ReturnContent:
1432 return (sb == null) ? value : sb.ToString();
1435 private bool SetupReadElementContentAsXxx(string methodName) {
1436 if (this.NodeType != XmlNodeType.Element) {
1437 throw CreateReadElementContentAsException(methodName);
1440 bool isEmptyElement = this.IsEmptyElement;
1442 // move to content or beyond the empty element
1443 this.Read();
1445 if (isEmptyElement) {
1446 return false;
1449 XmlNodeType nodeType = this.NodeType;
1450 if (nodeType == XmlNodeType.EndElement) {
1451 this.Read();
1452 return false;
1454 else if (nodeType == XmlNodeType.Element) {
1455 throw new XmlException(Res.Xml_MixedReadElementContentAs, string.Empty, this as IXmlLineInfo);
1457 return true;
1460 private void FinishReadElementContentAsXxx() {
1461 if (this.NodeType != XmlNodeType.EndElement) {
1462 throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString());
1464 this.Read();
1467 internal bool IsDefaultInternal {
1468 get {
1469 #if SILVERLIGHT // Removing dependency on XmlSchema
1470 return this.IsDefault;
1471 #else
1472 if (this.IsDefault) {
1473 return true;
1475 IXmlSchemaInfo schemaInfo = this.SchemaInfo;
1476 if (schemaInfo != null && schemaInfo.IsDefault) {
1477 return true;
1479 return false;
1480 #endif
1484 #if !SILVERLIGHT
1485 internal virtual IDtdInfo DtdInfo {
1486 get {
1487 return null;
1490 #endif
1492 #if !SILVERLIGHT // Needed only for XmlTextReader or XmlValidatingReader
1493 internal static Encoding GetEncoding(XmlReader reader) {
1494 XmlTextReaderImpl tri = GetXmlTextReaderImpl(reader);
1495 return tri != null ? tri.Encoding : null;
1497 #endif
1499 internal static ConformanceLevel GetV1ConformanceLevel(XmlReader reader) {
1500 XmlTextReaderImpl tri = GetXmlTextReaderImpl(reader);
1501 return tri != null ? tri.V1ComformanceLevel : ConformanceLevel.Document;
1504 private static XmlTextReaderImpl GetXmlTextReaderImpl(XmlReader reader) {
1505 XmlTextReaderImpl tri = reader as XmlTextReaderImpl;
1506 if (tri != null) {
1507 return tri;
1510 #if !SILVERLIGHT // Needed only for XmlTextReader or XmlValidatingReader
1511 XmlTextReader tr = reader as XmlTextReader;
1512 if (tr != null) {
1513 return tr.Impl;
1516 XmlValidatingReaderImpl vri = reader as XmlValidatingReaderImpl;
1517 if (vri != null) {
1518 return vri.ReaderImpl;
1520 #pragma warning disable 618
1521 XmlValidatingReader vr = reader as XmlValidatingReader;
1522 #pragma warning restore 618
1523 if (vr != null) {
1524 return vr.Impl.ReaderImpl;
1526 #endif
1527 return null;
1531 // Static methods for creating readers
1534 // Creates an XmlReader for parsing XML from the given Uri.
1535 #if !SILVERLIGHT
1536 [ResourceConsumption(ResourceScope.Machine)]
1537 [ResourceExposure(ResourceScope.Machine)]
1538 #endif
1539 public static XmlReader Create(string inputUri) {
1540 return XmlReader.Create(inputUri, (XmlReaderSettings)null, (XmlParserContext)null);
1543 // Creates an XmlReader according to the settings for parsing XML from the given Uri.
1544 #if !SILVERLIGHT
1545 [ResourceConsumption(ResourceScope.Machine)]
1546 [ResourceExposure(ResourceScope.Machine)]
1547 #endif
1548 public static XmlReader Create(string inputUri, XmlReaderSettings settings) {
1549 return XmlReader.Create(inputUri, settings, (XmlParserContext)null);
1552 // Creates an XmlReader according to the settings and parser context for parsing XML from the given Uri.
1553 #if !SILVERLIGHT
1554 [ResourceConsumption(ResourceScope.Machine)]
1555 [ResourceExposure(ResourceScope.Machine)]
1556 #endif
1557 public static XmlReader Create(String inputUri, XmlReaderSettings settings, XmlParserContext inputContext) {
1558 if (settings == null) {
1559 settings = new XmlReaderSettings();
1561 return settings.CreateReader(inputUri, inputContext);
1564 // Creates an XmlReader according for parsing XML from the given stream.
1565 public static XmlReader Create(Stream input) {
1566 return Create(input, (XmlReaderSettings)null, (string)string.Empty);
1569 // Creates an XmlReader according to the settings for parsing XML from the given stream.
1570 public static XmlReader Create(Stream input, XmlReaderSettings settings) {
1571 return Create(input, settings, string.Empty);
1574 // Creates an XmlReader according to the settings and base Uri for parsing XML from the given stream.
1575 public static XmlReader Create(Stream input, XmlReaderSettings settings, String baseUri) {
1576 if (settings == null) {
1577 settings = new XmlReaderSettings();
1579 return settings.CreateReader(input, null, (string)baseUri, null);
1582 // Creates an XmlReader according to the settings and parser context for parsing XML from the given stream.
1583 public static XmlReader Create(Stream input, XmlReaderSettings settings, XmlParserContext inputContext) {
1584 if (settings == null) {
1585 settings = new XmlReaderSettings();
1587 return settings.CreateReader(input, null, (string)string.Empty, inputContext);
1590 // Creates an XmlReader according for parsing XML from the given TextReader.
1591 public static XmlReader Create(TextReader input) {
1592 return Create(input, (XmlReaderSettings)null, (string)string.Empty);
1595 // Creates an XmlReader according to the settings for parsing XML from the given TextReader.
1596 public static XmlReader Create(TextReader input, XmlReaderSettings settings) {
1597 return Create(input, settings, string.Empty);
1600 // Creates an XmlReader according to the settings and baseUri for parsing XML from the given TextReader.
1601 public static XmlReader Create(TextReader input, XmlReaderSettings settings, String baseUri) {
1602 if (settings == null) {
1603 settings = new XmlReaderSettings();
1605 return settings.CreateReader(input, baseUri, null);
1608 // Creates an XmlReader according to the settings and parser context for parsing XML from the given TextReader.
1609 public static XmlReader Create(TextReader input, XmlReaderSettings settings, XmlParserContext inputContext) {
1610 if (settings == null) {
1611 settings = new XmlReaderSettings();
1613 return settings.CreateReader(input, string.Empty, inputContext);
1616 // Creates an XmlReader according to the settings wrapped over the given reader.
1617 public static XmlReader Create(XmlReader reader, XmlReaderSettings settings) {
1618 if (settings == null) {
1619 settings = new XmlReaderSettings();
1621 return settings.CreateReader(reader);
1624 #if !SILVERLIGHT
1625 // !!!!!!
1626 // NOTE: This method is called via reflection from System.Data.dll and from Analysis Services in Yukon.
1627 // Do not change its signature without notifying the appropriate teams!
1628 // !!!!!!
1629 internal static XmlReader CreateSqlReader(Stream input, XmlReaderSettings settings, XmlParserContext inputContext) {
1630 if (input == null) {
1631 throw new ArgumentNullException("input");
1633 if (settings == null) {
1634 settings = new XmlReaderSettings();
1637 XmlReader reader;
1639 // allocate byte buffer
1640 byte[] bytes = new byte[CalcBufferSize(input)];
1642 #if false
1644 // catch the binary XML input and dump it into a local file (for debugging and testing purposes)
1646 // create dump file name
1647 string dumpFileNameBase = "~CreateSqlReaderInputDump";
1648 string dumpFileName;
1649 int i = 0;
1650 do {
1651 i++;
1652 dumpFileName = Path.GetFullPath(string.Concat(dumpFileNameBase, i.ToString(), ".bmx"));
1653 } while (File.Exists(dumpFileName));
1655 // dump the input into the file
1656 FileStream fs = new FileStream(dumpFileName, FileMode.Create, FileAccess.ReadWrite);
1657 byte[] buffer = new byte[4096];
1658 int bytesRead;
1659 while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0) {
1660 fs.Write(buffer, 0, bytesRead);
1662 fs.Seek(0, SeekOrigin.Begin);
1664 // make sure it will get closed
1665 if (settings.CloseInput) {
1666 input.Close();
1668 input = fs;
1669 settings = settings.Clone();
1670 settings.CloseInput = true;
1672 #endif
1673 int byteCount = 0;
1674 int read;
1675 do {
1676 read = input.Read(bytes, byteCount, bytes.Length - byteCount);
1677 byteCount += read;
1678 } while (read > 0 && byteCount < 2);
1680 // create text or binary XML reader depenting on the stream first 2 bytes
1681 if (byteCount >= 2 && (bytes[0] == 0xdf && bytes[1] == 0xff)) {
1682 if ( inputContext != null )
1683 throw new ArgumentException(Res.GetString(Res.XmlBinary_NoParserContext), "inputContext");
1684 reader = new XmlSqlBinaryReader(input, bytes, byteCount, string.Empty, settings.CloseInput, settings);
1686 else {
1687 reader = new XmlTextReaderImpl(input, bytes, byteCount, settings, null, string.Empty, inputContext, settings.CloseInput);
1690 // wrap with validating reader
1691 if ( settings.ValidationType != ValidationType.None ) {
1692 reader = settings.AddValidation( reader );
1695 if (settings.Async) {
1696 reader = XmlAsyncCheckReader.CreateAsyncCheckWrapper(reader);
1699 return reader;
1701 #endif
1703 internal static int CalcBufferSize(Stream input) {
1704 // determine the size of byte buffer
1705 int bufferSize = DefaultBufferSize;
1706 if (input.CanSeek) {
1707 long len = input.Length;
1708 if (len < bufferSize) {
1709 bufferSize = checked((int)len);
1711 else if (len > MaxStreamLengthForDefaultBufferSize) {
1712 bufferSize = BiggerBufferSize;
1716 // return the byte buffer size
1717 return bufferSize;
1720 #if !SILVERLIGHT // This is used for displaying the state of the XmlReader in Watch/Locals windows in the Visual Studio during debugging
1721 private object debuggerDisplayProxy { get { return new XmlReaderDebuggerDisplayProxy(this); } }
1723 [DebuggerDisplay("{ToString()}")]
1724 struct XmlReaderDebuggerDisplayProxy {
1725 XmlReader reader;
1727 internal XmlReaderDebuggerDisplayProxy( XmlReader reader ) {
1728 this.reader = reader;
1731 public override string ToString() {
1732 XmlNodeType nt = reader.NodeType;
1733 string result = nt.ToString();
1734 switch ( nt ) {
1735 case XmlNodeType.Element:
1736 case XmlNodeType.EndElement:
1737 case XmlNodeType.EntityReference:
1738 case XmlNodeType.EndEntity:
1739 result += ", Name=\"" + reader.Name + '"';
1740 break;
1741 case XmlNodeType.Attribute:
1742 case XmlNodeType.ProcessingInstruction:
1743 result += ", Name=\"" + reader.Name + "\", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay( reader.Value ) + '"';
1744 break;
1745 case XmlNodeType.Text:
1746 case XmlNodeType.Whitespace:
1747 case XmlNodeType.SignificantWhitespace:
1748 case XmlNodeType.Comment:
1749 case XmlNodeType.XmlDeclaration:
1750 case XmlNodeType.CDATA:
1751 result += ", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay( reader.Value ) + '"';
1752 break;
1753 case XmlNodeType.DocumentType:
1754 result += ", Name=\"" + reader.Name + "'";
1755 result += ", SYSTEM=\"" + reader.GetAttribute( "SYSTEM" ) + '"';
1756 result += ", PUBLIC=\"" + reader.GetAttribute( "PUBLIC" ) + '"';
1757 result += ", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay( reader.Value ) + '"';
1758 break;
1760 return result;
1763 #endif