1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.IO; 6 using System.Text; 7 using System.Security; 8 using System.Diagnostics; 9 using System.Collections; 10 using System.Globalization; 11 using System.Xml.Schema; 12 using System.Runtime.Versioning; 13 14 namespace System.Xml 15 { 16 // Represents a reader that provides fast, non-cached forward only stream access to XML data. 17 [DebuggerDisplay("{debuggerDisplayProxy}")] 18 public abstract partial class XmlReader : IDisposable 19 { 20 private static uint s_isTextualNodeBitmap = 0x6018; // 00 0110 0000 0001 1000 21 // 0 None, 22 // 0 Element, 23 // 0 Attribute, 24 // 1 Text, 25 // 1 CDATA, 26 // 0 EntityReference, 27 // 0 Entity, 28 // 0 ProcessingInstruction, 29 // 0 Comment, 30 // 0 Document, 31 // 0 DocumentType, 32 // 0 DocumentFragment, 33 // 0 Notation, 34 // 1 Whitespace, 35 // 1 SignificantWhitespace, 36 // 0 EndElement, 37 // 0 EndEntity, 38 // 0 XmlDeclaration 39 40 private static uint s_canReadContentAsBitmap = 0x1E1BC; // 01 1110 0001 1011 1100 41 // 0 None, 42 // 0 Element, 43 // 1 Attribute, 44 // 1 Text, 45 // 1 CDATA, 46 // 1 EntityReference, 47 // 0 Entity, 48 // 1 ProcessingInstruction, 49 // 1 Comment, 50 // 0 Document, 51 // 0 DocumentType, 52 // 0 DocumentFragment, 53 // 0 Notation, 54 // 1 Whitespace, 55 // 1 SignificantWhitespace, 56 // 1 EndElement, 57 // 1 EndEntity, 58 // 0 XmlDeclaration 59 60 private static uint s_hasValueBitmap = 0x2659C; // 10 0110 0101 1001 1100 61 // 0 None, 62 // 0 Element, 63 // 1 Attribute, 64 // 1 Text, 65 // 1 CDATA, 66 // 0 EntityReference, 67 // 0 Entity, 68 // 1 ProcessingInstruction, 69 // 1 Comment, 70 // 0 Document, 71 // 1 DocumentType, 72 // 0 DocumentFragment, 73 // 0 Notation, 74 // 1 Whitespace, 75 // 1 SignificantWhitespace, 76 // 0 EndElement, 77 // 0 EndEntity, 78 // 1 XmlDeclaration 79 80 // 81 // Constants 82 // 83 internal const int DefaultBufferSize = 4096; 84 internal const int BiggerBufferSize = 8192; 85 internal const int MaxStreamLengthForDefaultBufferSize = 64 * 1024; // 64kB 86 87 internal const int AsyncBufferSize = 64 * 1024; //64KB 88 89 // Settings 90 public virtual XmlReaderSettings Settings 91 { 92 get 93 { 94 return null; 95 } 96 } 97 98 // Node Properties 99 // Get the type of the current node. 100 public abstract XmlNodeType NodeType { get; } 101 102 // Gets the name of the current node, including the namespace prefix. 103 public virtual string Name 104 { 105 get 106 { 107 if (Prefix.Length == 0) 108 { 109 return LocalName; 110 } 111 else 112 { 113 return NameTable.Add(string.Concat(Prefix, ":", LocalName)); 114 } 115 } 116 } 117 118 // Gets the name of the current node without the namespace prefix. 119 public abstract string LocalName { get; } 120 121 // Gets the namespace URN (as defined in the W3C Namespace Specification) of the current namespace scope. 122 public abstract string NamespaceURI { get; } 123 124 // Gets the namespace prefix associated with the current node. 125 public abstract string Prefix { get; } 126 127 // Gets a value indicating whether 128 public virtual bool HasValue 129 { 130 get 131 { 132 return HasValueInternal(this.NodeType); 133 } 134 } 135 136 // Gets the text value of the current node. 137 public abstract string Value { get; } 138 139 // Gets the depth of the current node in the XML element stack. 140 public abstract int Depth { get; } 141 142 // Gets the base URI of the current node. 143 public abstract string BaseURI { get; } 144 145 // Gets a value indicating whether the current node is an empty element (for example, <MyElement/>). 146 public abstract bool IsEmptyElement { get; } 147 148 // Gets a value indicating whether the current node is an attribute that was generated from the default value defined 149 // in the DTD or schema. 150 public virtual bool IsDefault 151 { 152 get 153 { 154 return false; 155 } 156 } 157 158 // Gets the quotation mark character used to enclose the value of an attribute node. 159 public virtual char QuoteChar 160 { 161 get 162 { 163 return '"'; 164 } 165 } 166 167 // Gets the current xml:space scope. 168 public virtual XmlSpace XmlSpace 169 { 170 get 171 { 172 return XmlSpace.None; 173 } 174 } 175 176 // Gets the current xml:lang scope. 177 public virtual string XmlLang 178 { 179 get 180 { 181 return string.Empty; 182 } 183 } 184 185 // returns the schema info interface of the reader 186 public virtual IXmlSchemaInfo SchemaInfo 187 { 188 get 189 { 190 return this as IXmlSchemaInfo; 191 } 192 } 193 194 // returns the type of the current node 195 public virtual System.Type ValueType 196 { 197 get 198 { 199 return typeof(string); 200 } 201 } 202 203 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 204 // and returns the content as the most appropriate type (by default as string). Stops at start tags and end tags. ReadContentAsObject()205 public virtual object ReadContentAsObject() 206 { 207 if (!CanReadContentAs()) 208 { 209 throw CreateReadContentAsException(nameof(ReadContentAsObject)); 210 } 211 return InternalReadContentAsString(); 212 } 213 214 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 215 // and converts the content to a boolean. Stops at start tags and end tags. ReadContentAsBoolean()216 public virtual bool ReadContentAsBoolean() 217 { 218 if (!CanReadContentAs()) 219 { 220 throw CreateReadContentAsException(nameof(ReadContentAsBoolean)); 221 } 222 try 223 { 224 return XmlConvert.ToBoolean(InternalReadContentAsString()); 225 } 226 catch (FormatException e) 227 { 228 throw new XmlException(SR.Xml_ReadContentAsFormatException, "Boolean", e, this as IXmlLineInfo); 229 } 230 } 231 232 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 233 // and converts the content to a DateTime. Stops at start tags and end tags. ReadContentAsDateTime()234 public virtual DateTime ReadContentAsDateTime() 235 { 236 if (!CanReadContentAs()) 237 { 238 throw CreateReadContentAsException(nameof(ReadContentAsDateTime)); 239 } 240 try 241 { 242 return XmlConvert.ToDateTime(InternalReadContentAsString(), XmlDateTimeSerializationMode.RoundtripKind); 243 } 244 catch (FormatException e) 245 { 246 throw new XmlException(SR.Xml_ReadContentAsFormatException, "DateTime", e, this as IXmlLineInfo); 247 } 248 } 249 250 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 251 // and converts the content to a DateTimeOffset. Stops at start tags and end tags. ReadContentAsDateTimeOffset()252 public virtual DateTimeOffset ReadContentAsDateTimeOffset() 253 { 254 if (!CanReadContentAs()) 255 { 256 throw CreateReadContentAsException(nameof(ReadContentAsDateTimeOffset)); 257 } 258 try 259 { 260 return XmlConvert.ToDateTimeOffset(InternalReadContentAsString()); 261 } 262 catch (FormatException e) 263 { 264 throw new XmlException(SR.Xml_ReadContentAsFormatException, "DateTimeOffset", e, this as IXmlLineInfo); 265 } 266 } 267 268 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 269 // and converts the content to a double. Stops at start tags and end tags. ReadContentAsDouble()270 public virtual double ReadContentAsDouble() 271 { 272 if (!CanReadContentAs()) 273 { 274 throw CreateReadContentAsException(nameof(ReadContentAsDouble)); 275 } 276 try 277 { 278 return XmlConvert.ToDouble(InternalReadContentAsString()); 279 } 280 catch (FormatException e) 281 { 282 throw new XmlException(SR.Xml_ReadContentAsFormatException, "Double", e, this as IXmlLineInfo); 283 } 284 } 285 286 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 287 // and converts the content to a float. Stops at start tags and end tags. ReadContentAsFloat()288 public virtual float ReadContentAsFloat() 289 { 290 if (!CanReadContentAs()) 291 { 292 throw CreateReadContentAsException(nameof(ReadContentAsFloat)); 293 } 294 try 295 { 296 return XmlConvert.ToSingle(InternalReadContentAsString()); 297 } 298 catch (FormatException e) 299 { 300 throw new XmlException(SR.Xml_ReadContentAsFormatException, "Float", e, this as IXmlLineInfo); 301 } 302 } 303 304 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 305 // and converts the content to a decimal. Stops at start tags and end tags. ReadContentAsDecimal()306 public virtual decimal ReadContentAsDecimal() 307 { 308 if (!CanReadContentAs()) 309 { 310 throw CreateReadContentAsException(nameof(ReadContentAsDecimal)); 311 } 312 try 313 { 314 return XmlConvert.ToDecimal(InternalReadContentAsString()); 315 } 316 catch (FormatException e) 317 { 318 throw new XmlException(SR.Xml_ReadContentAsFormatException, "Decimal", e, this as IXmlLineInfo); 319 } 320 } 321 322 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 323 // and converts the content to an int. Stops at start tags and end tags. ReadContentAsInt()324 public virtual int ReadContentAsInt() 325 { 326 if (!CanReadContentAs()) 327 { 328 throw CreateReadContentAsException(nameof(ReadContentAsInt)); 329 } 330 try 331 { 332 return XmlConvert.ToInt32(InternalReadContentAsString()); 333 } 334 catch (FormatException e) 335 { 336 throw new XmlException(SR.Xml_ReadContentAsFormatException, "Int", e, this as IXmlLineInfo); 337 } 338 } 339 340 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 341 // and converts the content to a long. Stops at start tags and end tags. ReadContentAsLong()342 public virtual long ReadContentAsLong() 343 { 344 if (!CanReadContentAs()) 345 { 346 throw CreateReadContentAsException(nameof(ReadContentAsLong)); 347 } 348 try 349 { 350 return XmlConvert.ToInt64(InternalReadContentAsString()); 351 } 352 catch (FormatException e) 353 { 354 throw new XmlException(SR.Xml_ReadContentAsFormatException, "Long", e, this as IXmlLineInfo); 355 } 356 } 357 358 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 359 // and returns the content as a string. Stops at start tags and end tags. ReadContentAsString()360 public virtual string ReadContentAsString() 361 { 362 if (!CanReadContentAs()) 363 { 364 throw CreateReadContentAsException(nameof(ReadContentAsString)); 365 } 366 return InternalReadContentAsString(); 367 } 368 369 // Concatenates values of textual nodes of the current content, ignoring comments and PIs, expanding entity references, 370 // and converts the content to the requested type. Stops at start tags and end tags. ReadContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver)371 public virtual object ReadContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver) 372 { 373 if (!CanReadContentAs()) 374 { 375 throw CreateReadContentAsException(nameof(ReadContentAs)); 376 } 377 378 string strContentValue = InternalReadContentAsString(); 379 if (returnType == typeof(string)) 380 { 381 return strContentValue; 382 } 383 else 384 { 385 try 386 { 387 return XmlUntypedStringConverter.Instance.FromString(strContentValue, returnType, (namespaceResolver == null ? this as IXmlNamespaceResolver : namespaceResolver)); 388 } 389 catch (FormatException e) 390 { 391 throw new XmlException(SR.Xml_ReadContentAsFormatException, returnType.ToString(), e, this as IXmlLineInfo); 392 } 393 catch (InvalidCastException e) 394 { 395 throw new XmlException(SR.Xml_ReadContentAsFormatException, returnType.ToString(), e, this as IXmlLineInfo); 396 } 397 } 398 } 399 400 // Returns the content of the current element as the most appropriate type. Moves to the node following the element's end tag. ReadElementContentAsObject()401 public virtual object ReadElementContentAsObject() 402 { 403 if (SetupReadElementContentAsXxx("ReadElementContentAsObject")) 404 { 405 object value = ReadContentAsObject(); 406 FinishReadElementContentAsXxx(); 407 return value; 408 } 409 return string.Empty; 410 } 411 412 // 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. ReadElementContentAsObject(string localName, string namespaceURI)413 public virtual object ReadElementContentAsObject(string localName, string namespaceURI) 414 { 415 CheckElement(localName, namespaceURI); 416 return ReadElementContentAsObject(); 417 } 418 419 // Returns the content of the current element as a boolean. Moves to the node following the element's end tag. ReadElementContentAsBoolean()420 public virtual bool ReadElementContentAsBoolean() 421 { 422 if (SetupReadElementContentAsXxx("ReadElementContentAsBoolean")) 423 { 424 bool value = ReadContentAsBoolean(); 425 FinishReadElementContentAsXxx(); 426 return value; 427 } 428 return XmlConvert.ToBoolean(string.Empty); 429 } 430 431 // 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. ReadElementContentAsBoolean(string localName, string namespaceURI)432 public virtual bool ReadElementContentAsBoolean(string localName, string namespaceURI) 433 { 434 CheckElement(localName, namespaceURI); 435 return ReadElementContentAsBoolean(); 436 } 437 438 // Returns the content of the current element as a DateTime. Moves to the node following the element's end tag. ReadElementContentAsDateTime()439 public virtual DateTime ReadElementContentAsDateTime() 440 { 441 if (SetupReadElementContentAsXxx("ReadElementContentAsDateTime")) 442 { 443 DateTime value = ReadContentAsDateTime(); 444 FinishReadElementContentAsXxx(); 445 return value; 446 } 447 return XmlConvert.ToDateTime(string.Empty, XmlDateTimeSerializationMode.RoundtripKind); 448 } 449 450 // Checks local name and namespace of the current element and returns its content as a DateTime. 451 // Moves to the node following the element's end tag. ReadElementContentAsDateTime(string localName, string namespaceURI)452 public virtual DateTime ReadElementContentAsDateTime(string localName, string namespaceURI) 453 { 454 CheckElement(localName, namespaceURI); 455 return ReadElementContentAsDateTime(); 456 } 457 458 // Returns the content of the current element as a double. Moves to the node following the element's end tag. ReadElementContentAsDouble()459 public virtual double ReadElementContentAsDouble() 460 { 461 if (SetupReadElementContentAsXxx("ReadElementContentAsDouble")) 462 { 463 double value = ReadContentAsDouble(); 464 FinishReadElementContentAsXxx(); 465 return value; 466 } 467 return XmlConvert.ToDouble(string.Empty); 468 } 469 470 // Checks local name and namespace of the current element and returns its content as a double. 471 // Moves to the node following the element's end tag. ReadElementContentAsDouble(string localName, string namespaceURI)472 public virtual double ReadElementContentAsDouble(string localName, string namespaceURI) 473 { 474 CheckElement(localName, namespaceURI); 475 return ReadElementContentAsDouble(); 476 } 477 478 // Returns the content of the current element as a float. Moves to the node following the element's end tag. ReadElementContentAsFloat()479 public virtual float ReadElementContentAsFloat() 480 { 481 if (SetupReadElementContentAsXxx("ReadElementContentAsFloat")) 482 { 483 float value = ReadContentAsFloat(); 484 FinishReadElementContentAsXxx(); 485 return value; 486 } 487 return XmlConvert.ToSingle(string.Empty); 488 } 489 490 // Checks local name and namespace of the current element and returns its content as a float. 491 // Moves to the node following the element's end tag. ReadElementContentAsFloat(string localName, string namespaceURI)492 public virtual float ReadElementContentAsFloat(string localName, string namespaceURI) 493 { 494 CheckElement(localName, namespaceURI); 495 return ReadElementContentAsFloat(); 496 } 497 498 // Returns the content of the current element as a decimal. Moves to the node following the element's end tag. ReadElementContentAsDecimal()499 public virtual decimal ReadElementContentAsDecimal() 500 { 501 if (SetupReadElementContentAsXxx("ReadElementContentAsDecimal")) 502 { 503 decimal value = ReadContentAsDecimal(); 504 FinishReadElementContentAsXxx(); 505 return value; 506 } 507 return XmlConvert.ToDecimal(string.Empty); 508 } 509 510 // Checks local name and namespace of the current element and returns its content as a decimal. 511 // Moves to the node following the element's end tag. ReadElementContentAsDecimal(string localName, string namespaceURI)512 public virtual decimal ReadElementContentAsDecimal(string localName, string namespaceURI) 513 { 514 CheckElement(localName, namespaceURI); 515 return ReadElementContentAsDecimal(); 516 } 517 518 // Returns the content of the current element as an int. Moves to the node following the element's end tag. ReadElementContentAsInt()519 public virtual int ReadElementContentAsInt() 520 { 521 if (SetupReadElementContentAsXxx("ReadElementContentAsInt")) 522 { 523 int value = ReadContentAsInt(); 524 FinishReadElementContentAsXxx(); 525 return value; 526 } 527 return XmlConvert.ToInt32(string.Empty); 528 } 529 530 // Checks local name and namespace of the current element and returns its content as an int. 531 // Moves to the node following the element's end tag. ReadElementContentAsInt(string localName, string namespaceURI)532 public virtual int ReadElementContentAsInt(string localName, string namespaceURI) 533 { 534 CheckElement(localName, namespaceURI); 535 return ReadElementContentAsInt(); 536 } 537 538 // Returns the content of the current element as a long. Moves to the node following the element's end tag. ReadElementContentAsLong()539 public virtual long ReadElementContentAsLong() 540 { 541 if (SetupReadElementContentAsXxx("ReadElementContentAsLong")) 542 { 543 long value = ReadContentAsLong(); 544 FinishReadElementContentAsXxx(); 545 return value; 546 } 547 return XmlConvert.ToInt64(string.Empty); 548 } 549 550 // Checks local name and namespace of the current element and returns its content as a long. 551 // Moves to the node following the element's end tag. ReadElementContentAsLong(string localName, string namespaceURI)552 public virtual long ReadElementContentAsLong(string localName, string namespaceURI) 553 { 554 CheckElement(localName, namespaceURI); 555 return ReadElementContentAsLong(); 556 } 557 558 // Returns the content of the current element as a string. Moves to the node following the element's end tag. ReadElementContentAsString()559 public virtual string ReadElementContentAsString() 560 { 561 if (SetupReadElementContentAsXxx("ReadElementContentAsString")) 562 { 563 string value = ReadContentAsString(); 564 FinishReadElementContentAsXxx(); 565 return value; 566 } 567 return string.Empty; 568 } 569 570 // Checks local name and namespace of the current element and returns its content as a string. 571 // Moves to the node following the element's end tag. ReadElementContentAsString(string localName, string namespaceURI)572 public virtual string ReadElementContentAsString(string localName, string namespaceURI) 573 { 574 CheckElement(localName, namespaceURI); 575 return ReadElementContentAsString(); 576 } 577 578 // Returns the content of the current element as the requested type. Moves to the node following the element's end tag. ReadElementContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver)579 public virtual object ReadElementContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver) 580 { 581 if (SetupReadElementContentAsXxx("ReadElementContentAs")) 582 { 583 object value = ReadContentAs(returnType, namespaceResolver); 584 FinishReadElementContentAsXxx(); 585 return value; 586 } 587 return (returnType == typeof(string)) ? string.Empty : XmlUntypedStringConverter.Instance.FromString(string.Empty, returnType, namespaceResolver); 588 } 589 590 // Checks local name and namespace of the current element and returns its content as the requested type. 591 // Moves to the node following the element's end tag. ReadElementContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver, string localName, string namespaceURI)592 public virtual object ReadElementContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver, string localName, string namespaceURI) 593 { 594 CheckElement(localName, namespaceURI); 595 return ReadElementContentAs(returnType, namespaceResolver); 596 } 597 598 // Attribute Accessors 599 // The number of attributes on the current node. 600 public abstract int AttributeCount { get; } 601 602 // Gets the value of the attribute with the specified Name GetAttribute(string name)603 public abstract string GetAttribute(string name); 604 605 // Gets the value of the attribute with the LocalName and NamespaceURI GetAttribute(string name, string namespaceURI)606 public abstract string GetAttribute(string name, string namespaceURI); 607 608 // Gets the value of the attribute with the specified index. GetAttribute(int i)609 public abstract string GetAttribute(int i); 610 611 // Gets the value of the attribute with the specified index. 612 public virtual string this[int i] 613 { 614 get 615 { 616 return GetAttribute(i); 617 } 618 } 619 620 // Gets the value of the attribute with the specified Name. 621 public virtual string this[string name] 622 { 623 get 624 { 625 return GetAttribute(name); 626 } 627 } 628 629 // Gets the value of the attribute with the LocalName and NamespaceURI 630 public virtual string this[string name, string namespaceURI] 631 { 632 get 633 { 634 return GetAttribute(name, namespaceURI); 635 } 636 } 637 638 // Moves to the attribute with the specified Name. MoveToAttribute(string name)639 public abstract bool MoveToAttribute(string name); 640 641 // Moves to the attribute with the specified LocalName and NamespaceURI. MoveToAttribute(string name, string ns)642 public abstract bool MoveToAttribute(string name, string ns); 643 644 // Moves to the attribute with the specified index. MoveToAttribute(int i)645 public virtual void MoveToAttribute(int i) 646 { 647 if (i < 0 || i >= AttributeCount) 648 { 649 throw new ArgumentOutOfRangeException(nameof(i)); 650 } 651 MoveToElement(); 652 MoveToFirstAttribute(); 653 int j = 0; 654 while (j < i) 655 { 656 MoveToNextAttribute(); 657 j++; 658 } 659 } 660 661 // Moves to the first attribute of the current node. MoveToFirstAttribute()662 public abstract bool MoveToFirstAttribute(); 663 664 // Moves to the next attribute. MoveToNextAttribute()665 public abstract bool MoveToNextAttribute(); 666 667 // Moves to the element that contains the current attribute node. MoveToElement()668 public abstract bool MoveToElement(); 669 670 // Parses the attribute value into one or more Text and/or EntityReference node types. 671 ReadAttributeValue()672 public abstract bool ReadAttributeValue(); 673 674 // Moving through the Stream 675 // Reads the next node from the stream. 676 Read()677 public abstract bool Read(); 678 679 // Returns true when the XmlReader is positioned at the end of the stream. 680 public abstract bool EOF { get; } 681 682 // Closes the stream/TextReader (if CloseInput==true), changes the ReadState to Closed, and sets all the properties back to zero/empty string. Close()683 public virtual void Close() { } 684 685 // Returns the read state of the XmlReader. 686 public abstract ReadState ReadState { get; } 687 688 // Skips to the end tag of the current element. Skip()689 public virtual void Skip() 690 { 691 if (ReadState != ReadState.Interactive) 692 { 693 return; 694 } 695 SkipSubtree(); 696 } 697 698 // Gets the XmlNameTable associated with the XmlReader. 699 public abstract XmlNameTable NameTable { get; } 700 701 // Resolves a namespace prefix in the current element's scope. LookupNamespace(string prefix)702 public abstract string LookupNamespace(string prefix); 703 704 // Returns true if the XmlReader can expand general entities. 705 public virtual bool CanResolveEntity 706 { 707 get 708 { 709 return false; 710 } 711 } 712 713 // Resolves the entity reference for nodes of NodeType EntityReference. ResolveEntity()714 public abstract void ResolveEntity(); 715 716 // Binary content access methods 717 // Returns true if the reader supports call to ReadContentAsBase64, ReadElementContentAsBase64, ReadContentAsBinHex and ReadElementContentAsBinHex. 718 public virtual bool CanReadBinaryContent 719 { 720 get 721 { 722 return false; 723 } 724 } 725 726 // Returns decoded bytes of the current base64 text content. Call this methods until it returns 0 to get all the data. ReadContentAsBase64(byte[] buffer, int index, int count)727 public virtual int ReadContentAsBase64(byte[] buffer, int index, int count) 728 { 729 throw new NotSupportedException(SR.Format(SR.Xml_ReadBinaryContentNotSupported, "ReadContentAsBase64")); 730 } 731 732 // Returns decoded bytes of the current base64 element content. Call this methods until it returns 0 to get all the data. ReadElementContentAsBase64(byte[] buffer, int index, int count)733 public virtual int ReadElementContentAsBase64(byte[] buffer, int index, int count) 734 { 735 throw new NotSupportedException(SR.Format(SR.Xml_ReadBinaryContentNotSupported, "ReadElementContentAsBase64")); 736 } 737 738 // Returns decoded bytes of the current binhex text content. Call this methods until it returns 0 to get all the data. ReadContentAsBinHex(byte[] buffer, int index, int count)739 public virtual int ReadContentAsBinHex(byte[] buffer, int index, int count) 740 { 741 throw new NotSupportedException(SR.Format(SR.Xml_ReadBinaryContentNotSupported, "ReadContentAsBinHex")); 742 } 743 744 // Returns decoded bytes of the current binhex element content. Call this methods until it returns 0 to get all the data. ReadElementContentAsBinHex(byte[] buffer, int index, int count)745 public virtual int ReadElementContentAsBinHex(byte[] buffer, int index, int count) 746 { 747 throw new NotSupportedException(SR.Format(SR.Xml_ReadBinaryContentNotSupported, "ReadElementContentAsBinHex")); 748 } 749 750 // Text streaming methods 751 752 // Returns true if the XmlReader supports calls to ReadValueChunk. 753 public virtual bool CanReadValueChunk 754 { 755 get 756 { 757 return false; 758 } 759 } 760 761 // Returns a chunk of the value of the current node. Call this method in a loop to get all the data. 762 // Use this method to get a streaming access to the value of the current node. ReadValueChunk(char[] buffer, int index, int count)763 public virtual int ReadValueChunk(char[] buffer, int index, int count) 764 { 765 throw new NotSupportedException(SR.Xml_ReadValueChunkNotSupported); 766 } 767 768 // Virtual helper methods 769 // Reads the contents of an element as a string. Stops of comments, PIs or entity references. 770 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ReadString()771 public virtual string ReadString() 772 { 773 if (this.ReadState != ReadState.Interactive) 774 { 775 return string.Empty; 776 } 777 this.MoveToElement(); 778 if (this.NodeType == XmlNodeType.Element) 779 { 780 if (this.IsEmptyElement) 781 { 782 return string.Empty; 783 } 784 else if (!this.Read()) 785 { 786 throw new InvalidOperationException(SR.Xml_InvalidOperation); 787 } 788 if (this.NodeType == XmlNodeType.EndElement) 789 { 790 return string.Empty; 791 } 792 } 793 string result = string.Empty; 794 while (IsTextualNode(this.NodeType)) 795 { 796 result += this.Value; 797 if (!this.Read()) 798 { 799 break; 800 } 801 } 802 return result; 803 } 804 805 // Checks whether the current node is a content (non-whitespace text, CDATA, Element, EndElement, EntityReference 806 // or EndEntity) node. If the node is not a content node, then the method skips ahead to the next content node or 807 // end of file. Skips over nodes of type ProcessingInstruction, DocumentType, Comment, Whitespace and SignificantWhitespace. MoveToContent()808 public virtual XmlNodeType MoveToContent() 809 { 810 do 811 { 812 switch (this.NodeType) 813 { 814 case XmlNodeType.Attribute: 815 MoveToElement(); 816 goto case XmlNodeType.Element; 817 case XmlNodeType.Element: 818 case XmlNodeType.EndElement: 819 case XmlNodeType.CDATA: 820 case XmlNodeType.Text: 821 case XmlNodeType.EntityReference: 822 case XmlNodeType.EndEntity: 823 return this.NodeType; 824 } 825 } while (Read()); 826 return this.NodeType; 827 } 828 829 // Checks that the current node is an element and advances the reader to the next node. ReadStartElement()830 public virtual void ReadStartElement() 831 { 832 if (MoveToContent() != XmlNodeType.Element) 833 { 834 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 835 } 836 Read(); 837 } 838 839 // Checks that the current content node is an element with the given Name and advances the reader to the next node. ReadStartElement(string name)840 public virtual void ReadStartElement(string name) 841 { 842 if (MoveToContent() != XmlNodeType.Element) 843 { 844 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 845 } 846 if (this.Name == name) 847 { 848 Read(); 849 } 850 else 851 { 852 throw new XmlException(SR.Xml_ElementNotFound, name, this as IXmlLineInfo); 853 } 854 } 855 856 // Checks that the current content node is an element with the given LocalName and NamespaceURI 857 // and advances the reader to the next node. ReadStartElement(string localname, string ns)858 public virtual void ReadStartElement(string localname, string ns) 859 { 860 if (MoveToContent() != XmlNodeType.Element) 861 { 862 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 863 } 864 if (this.LocalName == localname && this.NamespaceURI == ns) 865 { 866 Read(); 867 } 868 else 869 { 870 throw new XmlException(SR.Xml_ElementNotFoundNs, new string[2] { localname, ns }, this as IXmlLineInfo); 871 } 872 } 873 874 // Reads a text-only element. 875 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ReadElementString()876 public virtual string ReadElementString() 877 { 878 string result = string.Empty; 879 880 if (MoveToContent() != XmlNodeType.Element) 881 { 882 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 883 } 884 if (!this.IsEmptyElement) 885 { 886 Read(); 887 result = ReadString(); 888 if (this.NodeType != XmlNodeType.EndElement) 889 { 890 throw new XmlException(SR.Xml_UnexpectedNodeInSimpleContent, new string[] { this.NodeType.ToString(), "ReadElementString" }, this as IXmlLineInfo); 891 } 892 Read(); 893 } 894 else 895 { 896 Read(); 897 } 898 return result; 899 } 900 901 // Checks that the Name property of the element found matches the given string before reading a text-only element. 902 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ReadElementString(string name)903 public virtual string ReadElementString(string name) 904 { 905 string result = string.Empty; 906 907 if (MoveToContent() != XmlNodeType.Element) 908 { 909 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 910 } 911 if (this.Name != name) 912 { 913 throw new XmlException(SR.Xml_ElementNotFound, name, this as IXmlLineInfo); 914 } 915 916 if (!this.IsEmptyElement) 917 { 918 //Read(); 919 result = ReadString(); 920 if (this.NodeType != XmlNodeType.EndElement) 921 { 922 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 923 } 924 Read(); 925 } 926 else 927 { 928 Read(); 929 } 930 return result; 931 } 932 933 // Checks that the LocalName and NamespaceURI properties of the element found matches the given strings 934 // before reading a text-only element. 935 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ReadElementString(string localname, string ns)936 public virtual string ReadElementString(string localname, string ns) 937 { 938 string result = string.Empty; 939 if (MoveToContent() != XmlNodeType.Element) 940 { 941 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 942 } 943 if (this.LocalName != localname || this.NamespaceURI != ns) 944 { 945 throw new XmlException(SR.Xml_ElementNotFoundNs, new string[2] { localname, ns }, this as IXmlLineInfo); 946 } 947 948 if (!this.IsEmptyElement) 949 { 950 //Read(); 951 result = ReadString(); 952 if (this.NodeType != XmlNodeType.EndElement) 953 { 954 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 955 } 956 Read(); 957 } 958 else 959 { 960 Read(); 961 } 962 963 return result; 964 } 965 966 // Checks that the current content node is an end tag and advances the reader to the next node. ReadEndElement()967 public virtual void ReadEndElement() 968 { 969 if (MoveToContent() != XmlNodeType.EndElement) 970 { 971 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 972 } 973 Read(); 974 } 975 976 // Calls MoveToContent and tests if the current content node is a start tag or empty element tag (XmlNodeType.Element). IsStartElement()977 public virtual bool IsStartElement() 978 { 979 return MoveToContent() == XmlNodeType.Element; 980 } 981 982 // Calls MoveToContentand tests if the current content node is a start tag or empty element tag (XmlNodeType.Element) and if the 983 // Name property of the element found matches the given argument. IsStartElement(string name)984 public virtual bool IsStartElement(string name) 985 { 986 return (MoveToContent() == XmlNodeType.Element) && 987 (this.Name == name); 988 } 989 990 // Calls MoveToContent and tests if the current content node is a start tag or empty element tag (XmlNodeType.Element) and if 991 // the LocalName and NamespaceURI properties of the element found match the given strings. IsStartElement(string localname, string ns)992 public virtual bool IsStartElement(string localname, string ns) 993 { 994 return (MoveToContent() == XmlNodeType.Element) && 995 (this.LocalName == localname && this.NamespaceURI == ns); 996 } 997 998 // Reads to the following element with the given Name. ReadToFollowing(string name)999 public virtual bool ReadToFollowing(string name) 1000 { 1001 if (name == null || name.Length == 0) 1002 { 1003 throw XmlConvert.CreateInvalidNameArgumentException(name, nameof(name)); 1004 } 1005 // atomize name 1006 name = NameTable.Add(name); 1007 1008 // find following element with that name 1009 while (Read()) 1010 { 1011 if (NodeType == XmlNodeType.Element && Ref.Equal(name, Name)) 1012 { 1013 return true; 1014 } 1015 } 1016 return false; 1017 } 1018 1019 // Reads to the following element with the given LocalName and NamespaceURI. ReadToFollowing(string localName, string namespaceURI)1020 public virtual bool ReadToFollowing(string localName, string namespaceURI) 1021 { 1022 if (localName == null || localName.Length == 0) 1023 { 1024 throw XmlConvert.CreateInvalidNameArgumentException(localName, nameof(localName)); 1025 } 1026 if (namespaceURI == null) 1027 { 1028 throw new ArgumentNullException(nameof(namespaceURI)); 1029 } 1030 1031 // atomize local name and namespace 1032 localName = NameTable.Add(localName); 1033 namespaceURI = NameTable.Add(namespaceURI); 1034 1035 // find following element with that name 1036 while (Read()) 1037 { 1038 if (NodeType == XmlNodeType.Element && Ref.Equal(localName, LocalName) && Ref.Equal(namespaceURI, NamespaceURI)) 1039 { 1040 return true; 1041 } 1042 } 1043 return false; 1044 } 1045 1046 // Reads to the first descendant of the current element with the given Name. ReadToDescendant(string name)1047 public virtual bool ReadToDescendant(string name) 1048 { 1049 if (name == null || name.Length == 0) 1050 { 1051 throw XmlConvert.CreateInvalidNameArgumentException(name, nameof(name)); 1052 } 1053 // save the element or root depth 1054 int parentDepth = Depth; 1055 if (NodeType != XmlNodeType.Element) 1056 { 1057 // adjust the depth if we are on root node 1058 if (ReadState == ReadState.Initial) 1059 { 1060 Debug.Assert(parentDepth == 0); 1061 parentDepth--; 1062 } 1063 else 1064 { 1065 return false; 1066 } 1067 } 1068 else if (IsEmptyElement) 1069 { 1070 return false; 1071 } 1072 1073 // atomize name 1074 name = NameTable.Add(name); 1075 1076 // find the descendant 1077 while (Read() && Depth > parentDepth) 1078 { 1079 if (NodeType == XmlNodeType.Element && Ref.Equal(name, Name)) 1080 { 1081 return true; 1082 } 1083 } 1084 Debug.Assert(NodeType == XmlNodeType.EndElement || NodeType == XmlNodeType.None || ReadState == ReadState.Error); 1085 return false; 1086 } 1087 1088 // Reads to the first descendant of the current element with the given LocalName and NamespaceURI. ReadToDescendant(string localName, string namespaceURI)1089 public virtual bool ReadToDescendant(string localName, string namespaceURI) 1090 { 1091 if (localName == null || localName.Length == 0) 1092 { 1093 throw XmlConvert.CreateInvalidNameArgumentException(localName, nameof(localName)); 1094 } 1095 if (namespaceURI == null) 1096 { 1097 throw new ArgumentNullException(nameof(namespaceURI)); 1098 } 1099 // save the element or root depth 1100 int parentDepth = Depth; 1101 if (NodeType != XmlNodeType.Element) 1102 { 1103 // adjust the depth if we are on root node 1104 if (ReadState == ReadState.Initial) 1105 { 1106 Debug.Assert(parentDepth == 0); 1107 parentDepth--; 1108 } 1109 else 1110 { 1111 return false; 1112 } 1113 } 1114 else if (IsEmptyElement) 1115 { 1116 return false; 1117 } 1118 1119 // atomize local name and namespace 1120 localName = NameTable.Add(localName); 1121 namespaceURI = NameTable.Add(namespaceURI); 1122 1123 // find the descendant 1124 while (Read() && Depth > parentDepth) 1125 { 1126 if (NodeType == XmlNodeType.Element && Ref.Equal(localName, LocalName) && Ref.Equal(namespaceURI, NamespaceURI)) 1127 { 1128 return true; 1129 } 1130 } 1131 Debug.Assert(NodeType == XmlNodeType.EndElement); 1132 return false; 1133 } 1134 1135 // Reads to the next sibling of the current element with the given Name. ReadToNextSibling(string name)1136 public virtual bool ReadToNextSibling(string name) 1137 { 1138 if (name == null || name.Length == 0) 1139 { 1140 throw XmlConvert.CreateInvalidNameArgumentException(name, nameof(name)); 1141 } 1142 1143 // atomize name 1144 name = NameTable.Add(name); 1145 1146 // find the next sibling 1147 XmlNodeType nt; 1148 do 1149 { 1150 if (!SkipSubtree()) 1151 { 1152 break; 1153 } 1154 nt = NodeType; 1155 if (nt == XmlNodeType.Element && Ref.Equal(name, Name)) 1156 { 1157 return true; 1158 } 1159 } while (nt != XmlNodeType.EndElement && !EOF); 1160 return false; 1161 } 1162 1163 // Reads to the next sibling of the current element with the given LocalName and NamespaceURI. ReadToNextSibling(string localName, string namespaceURI)1164 public virtual bool ReadToNextSibling(string localName, string namespaceURI) 1165 { 1166 if (localName == null || localName.Length == 0) 1167 { 1168 throw XmlConvert.CreateInvalidNameArgumentException(localName, nameof(localName)); 1169 } 1170 if (namespaceURI == null) 1171 { 1172 throw new ArgumentNullException(nameof(namespaceURI)); 1173 } 1174 1175 // atomize local name and namespace 1176 localName = NameTable.Add(localName); 1177 namespaceURI = NameTable.Add(namespaceURI); 1178 1179 // find the next sibling 1180 XmlNodeType nt; 1181 do 1182 { 1183 if (!SkipSubtree()) 1184 { 1185 break; 1186 } 1187 nt = NodeType; 1188 if (nt == XmlNodeType.Element && Ref.Equal(localName, LocalName) && Ref.Equal(namespaceURI, NamespaceURI)) 1189 { 1190 return true; 1191 } 1192 } while (nt != XmlNodeType.EndElement && !EOF); 1193 return false; 1194 } 1195 1196 // Returns true if the given argument is a valid Name. IsName(string str)1197 public static bool IsName(string str) 1198 { 1199 if (str == null) 1200 { 1201 throw new NullReferenceException(); 1202 } 1203 return ValidateNames.IsNameNoNamespaces(str); 1204 } 1205 1206 // Returns true if the given argument is a valid NmToken. IsNameToken(string str)1207 public static bool IsNameToken(string str) 1208 { 1209 if (str == null) 1210 { 1211 throw new NullReferenceException(); 1212 } 1213 return ValidateNames.IsNmtokenNoNamespaces(str); 1214 } 1215 1216 // Returns the inner content (including markup) of an element or attribute as a string. ReadInnerXml()1217 public virtual string ReadInnerXml() 1218 { 1219 if (ReadState != ReadState.Interactive) 1220 { 1221 return string.Empty; 1222 } 1223 if ((this.NodeType != XmlNodeType.Attribute) && (this.NodeType != XmlNodeType.Element)) 1224 { 1225 Read(); 1226 return string.Empty; 1227 } 1228 1229 StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); 1230 XmlWriter xtw = CreateWriterForInnerOuterXml(sw); 1231 1232 try 1233 { 1234 if (this.NodeType == XmlNodeType.Attribute) 1235 { 1236 ((XmlTextWriter)xtw).QuoteChar = this.QuoteChar; 1237 WriteAttributeValue(xtw); 1238 } 1239 if (this.NodeType == XmlNodeType.Element) 1240 { 1241 this.WriteNode(xtw, false); 1242 } 1243 } 1244 finally 1245 { 1246 xtw.Close(); 1247 } 1248 return sw.ToString(); 1249 } 1250 1251 // Writes the content (inner XML) of the current node into the provided XmlWriter. WriteNode(XmlWriter xtw, bool defattr)1252 private void WriteNode(XmlWriter xtw, bool defattr) 1253 { 1254 Debug.Assert(xtw is XmlTextWriter); 1255 int d = this.NodeType == XmlNodeType.None ? -1 : this.Depth; 1256 while (this.Read() && (d < this.Depth)) 1257 { 1258 switch (this.NodeType) 1259 { 1260 case XmlNodeType.Element: 1261 xtw.WriteStartElement(this.Prefix, this.LocalName, this.NamespaceURI); 1262 ((XmlTextWriter)xtw).QuoteChar = this.QuoteChar; 1263 xtw.WriteAttributes(this, defattr); 1264 if (this.IsEmptyElement) 1265 { 1266 xtw.WriteEndElement(); 1267 } 1268 break; 1269 case XmlNodeType.Text: 1270 xtw.WriteString(this.Value); 1271 break; 1272 case XmlNodeType.Whitespace: 1273 case XmlNodeType.SignificantWhitespace: 1274 xtw.WriteWhitespace(this.Value); 1275 break; 1276 case XmlNodeType.CDATA: 1277 xtw.WriteCData(this.Value); 1278 break; 1279 case XmlNodeType.EntityReference: 1280 xtw.WriteEntityRef(this.Name); 1281 break; 1282 case XmlNodeType.XmlDeclaration: 1283 case XmlNodeType.ProcessingInstruction: 1284 xtw.WriteProcessingInstruction(this.Name, this.Value); 1285 break; 1286 case XmlNodeType.DocumentType: 1287 xtw.WriteDocType(this.Name, this.GetAttribute("PUBLIC"), this.GetAttribute("SYSTEM"), this.Value); 1288 break; 1289 case XmlNodeType.Comment: 1290 xtw.WriteComment(this.Value); 1291 break; 1292 case XmlNodeType.EndElement: 1293 xtw.WriteFullEndElement(); 1294 break; 1295 } 1296 } 1297 if (d == this.Depth && this.NodeType == XmlNodeType.EndElement) 1298 { 1299 Read(); 1300 } 1301 } 1302 1303 // Writes the attribute into the provided XmlWriter. WriteAttributeValue(XmlWriter xtw)1304 private void WriteAttributeValue(XmlWriter xtw) 1305 { 1306 string attrName = this.Name; 1307 while (ReadAttributeValue()) 1308 { 1309 if (this.NodeType == XmlNodeType.EntityReference) 1310 { 1311 xtw.WriteEntityRef(this.Name); 1312 } 1313 else 1314 { 1315 xtw.WriteString(this.Value); 1316 } 1317 } 1318 this.MoveToAttribute(attrName); 1319 } 1320 1321 // Returns the current element and its descendants or an attribute as a string. ReadOuterXml()1322 public virtual string ReadOuterXml() 1323 { 1324 if (ReadState != ReadState.Interactive) 1325 { 1326 return string.Empty; 1327 } 1328 if ((this.NodeType != XmlNodeType.Attribute) && (this.NodeType != XmlNodeType.Element)) 1329 { 1330 Read(); 1331 return string.Empty; 1332 } 1333 1334 StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); 1335 XmlWriter xtw = CreateWriterForInnerOuterXml(sw); 1336 1337 try 1338 { 1339 if (this.NodeType == XmlNodeType.Attribute) 1340 { 1341 xtw.WriteStartAttribute(this.Prefix, this.LocalName, this.NamespaceURI); 1342 WriteAttributeValue(xtw); 1343 xtw.WriteEndAttribute(); 1344 } 1345 else 1346 { 1347 xtw.WriteNode(this, false); 1348 } 1349 } 1350 finally 1351 { 1352 xtw.Close(); 1353 } 1354 return sw.ToString(); 1355 } 1356 CreateWriterForInnerOuterXml(StringWriter sw)1357 private XmlWriter CreateWriterForInnerOuterXml(StringWriter sw) 1358 { 1359 XmlTextWriter w = new XmlTextWriter(sw); 1360 // This is a V1 hack; we can put a custom implementation of ReadOuterXml on XmlTextReader/XmlValidatingReader 1361 SetNamespacesFlag(w); 1362 return w; 1363 } 1364 SetNamespacesFlag(XmlTextWriter xtw)1365 private void SetNamespacesFlag(XmlTextWriter xtw) 1366 { 1367 XmlTextReader tr = this as XmlTextReader; 1368 if (tr != null) 1369 { 1370 xtw.Namespaces = tr.Namespaces; 1371 } 1372 else 1373 { 1374 #pragma warning disable 618 1375 XmlValidatingReader vr = this as XmlValidatingReader; 1376 if (vr != null) 1377 { 1378 xtw.Namespaces = vr.Namespaces; 1379 } 1380 } 1381 #pragma warning restore 618 1382 } 1383 1384 // Returns an XmlReader that will read only the current element and its descendants and then go to EOF state. ReadSubtree()1385 public virtual XmlReader ReadSubtree() 1386 { 1387 if (NodeType != XmlNodeType.Element) 1388 { 1389 throw new InvalidOperationException(SR.Xml_ReadSubtreeNotOnElement); 1390 } 1391 return new XmlSubtreeReader(this); 1392 } 1393 1394 // Returns true when the current node has any attributes. 1395 public virtual bool HasAttributes 1396 { 1397 get 1398 { 1399 return AttributeCount > 0; 1400 } 1401 } 1402 1403 // 1404 // IDisposable interface 1405 // Dispose()1406 public void Dispose() 1407 { 1408 Dispose(true); 1409 } 1410 Dispose(bool disposing)1411 protected virtual void Dispose(bool disposing) 1412 { 1413 if (disposing && ReadState != ReadState.Closed) 1414 { 1415 Close(); 1416 } 1417 } 1418 1419 // 1420 // Internal methods 1421 // 1422 // Validation support 1423 internal virtual XmlNamespaceManager NamespaceManager 1424 { 1425 get 1426 { 1427 return null; 1428 } 1429 } 1430 IsTextualNode(XmlNodeType nodeType)1431 internal static bool IsTextualNode(XmlNodeType nodeType) 1432 { 1433 #if DEBUG 1434 // This code verifies IsTextualNodeBitmap mapping of XmlNodeType to a bool specifying 1435 // whether the node is 'textual' = Text, CDATA, Whitespace or SignificantWhitespace. 1436 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.None))); 1437 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.Element))); 1438 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.Attribute))); 1439 Debug.Assert(0 != (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.Text))); 1440 Debug.Assert(0 != (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.CDATA))); 1441 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.EntityReference))); 1442 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.Entity))); 1443 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.ProcessingInstruction))); 1444 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.Comment))); 1445 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.Document))); 1446 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.DocumentType))); 1447 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.DocumentFragment))); 1448 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.Notation))); 1449 Debug.Assert(0 != (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.Whitespace))); 1450 Debug.Assert(0 != (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.SignificantWhitespace))); 1451 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.EndElement))); 1452 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.EndEntity))); 1453 Debug.Assert(0 == (s_isTextualNodeBitmap & (1 << (int)XmlNodeType.XmlDeclaration))); 1454 #endif 1455 return 0 != (s_isTextualNodeBitmap & (1 << (int)nodeType)); 1456 } 1457 CanReadContentAs(XmlNodeType nodeType)1458 internal static bool CanReadContentAs(XmlNodeType nodeType) 1459 { 1460 #if DEBUG 1461 // This code verifies IsTextualNodeBitmap mapping of XmlNodeType to a bool specifying 1462 // whether ReadContentAsXxx calls are allowed on his node type 1463 Debug.Assert(0 == (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.None))); 1464 Debug.Assert(0 == (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.Element))); 1465 Debug.Assert(0 != (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.Attribute))); 1466 Debug.Assert(0 != (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.Text))); 1467 Debug.Assert(0 != (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.CDATA))); 1468 Debug.Assert(0 != (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.EntityReference))); 1469 Debug.Assert(0 == (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.Entity))); 1470 Debug.Assert(0 != (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.ProcessingInstruction))); 1471 Debug.Assert(0 != (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.Comment))); 1472 Debug.Assert(0 == (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.Document))); 1473 Debug.Assert(0 == (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.DocumentType))); 1474 Debug.Assert(0 == (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.DocumentFragment))); 1475 Debug.Assert(0 == (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.Notation))); 1476 Debug.Assert(0 != (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.Whitespace))); 1477 Debug.Assert(0 != (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.SignificantWhitespace))); 1478 Debug.Assert(0 != (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.EndElement))); 1479 Debug.Assert(0 != (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.EndEntity))); 1480 Debug.Assert(0 == (s_canReadContentAsBitmap & (1 << (int)XmlNodeType.XmlDeclaration))); 1481 #endif 1482 return 0 != (s_canReadContentAsBitmap & (1 << (int)nodeType)); 1483 } 1484 HasValueInternal(XmlNodeType nodeType)1485 internal static bool HasValueInternal(XmlNodeType nodeType) 1486 { 1487 #if DEBUG 1488 // This code verifies HasValueBitmap mapping of XmlNodeType to a bool specifying 1489 // whether the node can have a non-empty Value 1490 Debug.Assert(0 == (s_hasValueBitmap & (1 << (int)XmlNodeType.None))); 1491 Debug.Assert(0 == (s_hasValueBitmap & (1 << (int)XmlNodeType.Element))); 1492 Debug.Assert(0 != (s_hasValueBitmap & (1 << (int)XmlNodeType.Attribute))); 1493 Debug.Assert(0 != (s_hasValueBitmap & (1 << (int)XmlNodeType.Text))); 1494 Debug.Assert(0 != (s_hasValueBitmap & (1 << (int)XmlNodeType.CDATA))); 1495 Debug.Assert(0 == (s_hasValueBitmap & (1 << (int)XmlNodeType.EntityReference))); 1496 Debug.Assert(0 == (s_hasValueBitmap & (1 << (int)XmlNodeType.Entity))); 1497 Debug.Assert(0 != (s_hasValueBitmap & (1 << (int)XmlNodeType.ProcessingInstruction))); 1498 Debug.Assert(0 != (s_hasValueBitmap & (1 << (int)XmlNodeType.Comment))); 1499 Debug.Assert(0 == (s_hasValueBitmap & (1 << (int)XmlNodeType.Document))); 1500 Debug.Assert(0 != (s_hasValueBitmap & (1 << (int)XmlNodeType.DocumentType))); 1501 Debug.Assert(0 == (s_hasValueBitmap & (1 << (int)XmlNodeType.DocumentFragment))); 1502 Debug.Assert(0 == (s_hasValueBitmap & (1 << (int)XmlNodeType.Notation))); 1503 Debug.Assert(0 != (s_hasValueBitmap & (1 << (int)XmlNodeType.Whitespace))); 1504 Debug.Assert(0 != (s_hasValueBitmap & (1 << (int)XmlNodeType.SignificantWhitespace))); 1505 Debug.Assert(0 == (s_hasValueBitmap & (1 << (int)XmlNodeType.EndElement))); 1506 Debug.Assert(0 == (s_hasValueBitmap & (1 << (int)XmlNodeType.EndEntity))); 1507 Debug.Assert(0 != (s_hasValueBitmap & (1 << (int)XmlNodeType.XmlDeclaration))); 1508 #endif 1509 return 0 != (s_hasValueBitmap & (1 << (int)nodeType)); 1510 } 1511 1512 // 1513 // Private methods 1514 // 1515 //SkipSubTree is called whenever validation of the skipped subtree is required on a reader with XsdValidation SkipSubtree()1516 private bool SkipSubtree() 1517 { 1518 MoveToElement(); 1519 if (NodeType == XmlNodeType.Element && !IsEmptyElement) 1520 { 1521 int depth = Depth; 1522 1523 while (Read() && depth < Depth) 1524 { 1525 // Nothing, just read on 1526 } 1527 1528 // consume end tag 1529 if (NodeType == XmlNodeType.EndElement) 1530 return Read(); 1531 } 1532 else 1533 { 1534 return Read(); 1535 } 1536 1537 return false; 1538 } 1539 CheckElement(string localName, string namespaceURI)1540 internal void CheckElement(string localName, string namespaceURI) 1541 { 1542 if (localName == null || localName.Length == 0) 1543 { 1544 throw XmlConvert.CreateInvalidNameArgumentException(localName, nameof(localName)); 1545 } 1546 if (namespaceURI == null) 1547 { 1548 throw new ArgumentNullException(nameof(namespaceURI)); 1549 } 1550 if (NodeType != XmlNodeType.Element) 1551 { 1552 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 1553 } 1554 if (LocalName != localName || NamespaceURI != namespaceURI) 1555 { 1556 throw new XmlException(SR.Xml_ElementNotFoundNs, new string[2] { localName, namespaceURI }, this as IXmlLineInfo); 1557 } 1558 } 1559 CreateReadContentAsException(string methodName)1560 internal Exception CreateReadContentAsException(string methodName) 1561 { 1562 return CreateReadContentAsException(methodName, NodeType, this as IXmlLineInfo); 1563 } 1564 CreateReadElementContentAsException(string methodName)1565 internal Exception CreateReadElementContentAsException(string methodName) 1566 { 1567 return CreateReadElementContentAsException(methodName, NodeType, this as IXmlLineInfo); 1568 } 1569 CanReadContentAs()1570 internal bool CanReadContentAs() 1571 { 1572 return CanReadContentAs(this.NodeType); 1573 } 1574 CreateReadContentAsException(string methodName, XmlNodeType nodeType, IXmlLineInfo lineInfo)1575 internal static Exception CreateReadContentAsException(string methodName, XmlNodeType nodeType, IXmlLineInfo lineInfo) 1576 { 1577 return new InvalidOperationException(AddLineInfo(SR.Format(SR.Xml_InvalidReadContentAs, new string[] { methodName, nodeType.ToString() }), lineInfo)); 1578 } 1579 CreateReadElementContentAsException(string methodName, XmlNodeType nodeType, IXmlLineInfo lineInfo)1580 internal static Exception CreateReadElementContentAsException(string methodName, XmlNodeType nodeType, IXmlLineInfo lineInfo) 1581 { 1582 return new InvalidOperationException(AddLineInfo(SR.Format(SR.Xml_InvalidReadElementContentAs, new string[] { methodName, nodeType.ToString() }), lineInfo)); 1583 } 1584 AddLineInfo(string message, IXmlLineInfo lineInfo)1585 private static string AddLineInfo(string message, IXmlLineInfo lineInfo) 1586 { 1587 if (lineInfo != null) 1588 { 1589 string[] lineArgs = new string[2]; 1590 lineArgs[0] = lineInfo.LineNumber.ToString(CultureInfo.InvariantCulture); 1591 lineArgs[1] = lineInfo.LinePosition.ToString(CultureInfo.InvariantCulture); 1592 message += " " + SR.Format(SR.Xml_ErrorPosition, lineArgs); 1593 } 1594 return message; 1595 } 1596 InternalReadContentAsString()1597 internal string InternalReadContentAsString() 1598 { 1599 string value = string.Empty; 1600 StringBuilder sb = null; 1601 do 1602 { 1603 switch (this.NodeType) 1604 { 1605 case XmlNodeType.Attribute: 1606 return this.Value; 1607 case XmlNodeType.Text: 1608 case XmlNodeType.Whitespace: 1609 case XmlNodeType.SignificantWhitespace: 1610 case XmlNodeType.CDATA: 1611 // merge text content 1612 if (value.Length == 0) 1613 { 1614 value = this.Value; 1615 } 1616 else 1617 { 1618 if (sb == null) 1619 { 1620 sb = new StringBuilder(); 1621 sb.Append(value); 1622 } 1623 sb.Append(this.Value); 1624 } 1625 break; 1626 case XmlNodeType.ProcessingInstruction: 1627 case XmlNodeType.Comment: 1628 case XmlNodeType.EndEntity: 1629 // skip comments, pis and end entity nodes 1630 break; 1631 case XmlNodeType.EntityReference: 1632 if (this.CanResolveEntity) 1633 { 1634 this.ResolveEntity(); 1635 break; 1636 } 1637 goto default; 1638 case XmlNodeType.EndElement: 1639 default: 1640 goto ReturnContent; 1641 } 1642 } while ((this.AttributeCount != 0) ? this.ReadAttributeValue() : this.Read()); 1643 1644 ReturnContent: 1645 return (sb == null) ? value : sb.ToString(); 1646 } 1647 SetupReadElementContentAsXxx(string methodName)1648 private bool SetupReadElementContentAsXxx(string methodName) 1649 { 1650 if (this.NodeType != XmlNodeType.Element) 1651 { 1652 throw CreateReadElementContentAsException(methodName); 1653 } 1654 1655 bool isEmptyElement = this.IsEmptyElement; 1656 1657 // move to content or beyond the empty element 1658 this.Read(); 1659 1660 if (isEmptyElement) 1661 { 1662 return false; 1663 } 1664 1665 XmlNodeType nodeType = this.NodeType; 1666 if (nodeType == XmlNodeType.EndElement) 1667 { 1668 this.Read(); 1669 return false; 1670 } 1671 else if (nodeType == XmlNodeType.Element) 1672 { 1673 throw new XmlException(SR.Xml_MixedReadElementContentAs, string.Empty, this as IXmlLineInfo); 1674 } 1675 return true; 1676 } 1677 FinishReadElementContentAsXxx()1678 private void FinishReadElementContentAsXxx() 1679 { 1680 if (this.NodeType != XmlNodeType.EndElement) 1681 { 1682 throw new XmlException(SR.Xml_InvalidNodeType, this.NodeType.ToString()); 1683 } 1684 this.Read(); 1685 } 1686 1687 internal bool IsDefaultInternal 1688 { 1689 get 1690 { 1691 if (this.IsDefault) 1692 { 1693 return true; 1694 } 1695 IXmlSchemaInfo schemaInfo = this.SchemaInfo; 1696 if (schemaInfo != null && schemaInfo.IsDefault) 1697 { 1698 return true; 1699 } 1700 return false; 1701 } 1702 } 1703 1704 internal virtual IDtdInfo DtdInfo 1705 { 1706 get 1707 { 1708 return null; 1709 } 1710 } 1711 GetV1ConformanceLevel(XmlReader reader)1712 internal static ConformanceLevel GetV1ConformanceLevel(XmlReader reader) 1713 { 1714 XmlTextReaderImpl tri = GetXmlTextReaderImpl(reader); 1715 return tri != null ? tri.V1ComformanceLevel : ConformanceLevel.Document; 1716 } 1717 GetXmlTextReaderImpl(XmlReader reader)1718 private static XmlTextReaderImpl GetXmlTextReaderImpl(XmlReader reader) 1719 { 1720 XmlTextReaderImpl tri = reader as XmlTextReaderImpl; 1721 if (tri != null) 1722 { 1723 return tri; 1724 } 1725 1726 XmlTextReader tr = reader as XmlTextReader; 1727 if (tr != null) 1728 { 1729 return tr.Impl; 1730 } 1731 1732 XmlValidatingReaderImpl vri = reader as XmlValidatingReaderImpl; 1733 if (vri != null) 1734 { 1735 return vri.ReaderImpl; 1736 } 1737 #pragma warning disable 618 1738 XmlValidatingReader vr = reader as XmlValidatingReader; 1739 #pragma warning restore 618 1740 if (vr != null) 1741 { 1742 return vr.Impl.ReaderImpl; 1743 } 1744 1745 return null; 1746 } 1747 1748 // 1749 // Static methods for creating readers 1750 // 1751 1752 // Creates an XmlReader for parsing XML from the given Uri. Create(string inputUri)1753 public static XmlReader Create(string inputUri) 1754 { 1755 return XmlReader.Create(inputUri, (XmlReaderSettings)null, (XmlParserContext)null); 1756 } 1757 1758 // Creates an XmlReader according to the settings for parsing XML from the given Uri. Create(string inputUri, XmlReaderSettings settings)1759 public static XmlReader Create(string inputUri, XmlReaderSettings settings) 1760 { 1761 return XmlReader.Create(inputUri, settings, (XmlParserContext)null); 1762 } 1763 1764 // Creates an XmlReader according to the settings and parser context for parsing XML from the given Uri. Create(String inputUri, XmlReaderSettings settings, XmlParserContext inputContext)1765 public static XmlReader Create(String inputUri, XmlReaderSettings settings, XmlParserContext inputContext) 1766 { 1767 if (settings == null) 1768 { 1769 settings = new XmlReaderSettings(); 1770 } 1771 return settings.CreateReader(inputUri, inputContext); 1772 } 1773 1774 // Creates an XmlReader according for parsing XML from the given stream. Create(Stream input)1775 public static XmlReader Create(Stream input) 1776 { 1777 return Create(input, (XmlReaderSettings)null, (string)string.Empty); 1778 } 1779 1780 // Creates an XmlReader according to the settings for parsing XML from the given stream. Create(Stream input, XmlReaderSettings settings)1781 public static XmlReader Create(Stream input, XmlReaderSettings settings) 1782 { 1783 return Create(input, settings, string.Empty); 1784 } 1785 1786 // Creates an XmlReader according to the settings and base Uri for parsing XML from the given stream. Create(Stream input, XmlReaderSettings settings, String baseUri)1787 public static XmlReader Create(Stream input, XmlReaderSettings settings, String baseUri) 1788 { 1789 if (settings == null) 1790 { 1791 settings = new XmlReaderSettings(); 1792 } 1793 return settings.CreateReader(input, null, (string)baseUri, null); 1794 } 1795 1796 // Creates an XmlReader according to the settings and parser context for parsing XML from the given stream. Create(Stream input, XmlReaderSettings settings, XmlParserContext inputContext)1797 public static XmlReader Create(Stream input, XmlReaderSettings settings, XmlParserContext inputContext) 1798 { 1799 if (settings == null) 1800 { 1801 settings = new XmlReaderSettings(); 1802 } 1803 return settings.CreateReader(input, null, (string)string.Empty, inputContext); 1804 } 1805 1806 // Creates an XmlReader according for parsing XML from the given TextReader. Create(TextReader input)1807 public static XmlReader Create(TextReader input) 1808 { 1809 return Create(input, (XmlReaderSettings)null, (string)string.Empty); 1810 } 1811 1812 // Creates an XmlReader according to the settings for parsing XML from the given TextReader. Create(TextReader input, XmlReaderSettings settings)1813 public static XmlReader Create(TextReader input, XmlReaderSettings settings) 1814 { 1815 return Create(input, settings, string.Empty); 1816 } 1817 1818 // Creates an XmlReader according to the settings and baseUri for parsing XML from the given TextReader. Create(TextReader input, XmlReaderSettings settings, String baseUri)1819 public static XmlReader Create(TextReader input, XmlReaderSettings settings, String baseUri) 1820 { 1821 if (settings == null) 1822 { 1823 settings = new XmlReaderSettings(); 1824 } 1825 return settings.CreateReader(input, baseUri, null); 1826 } 1827 1828 // Creates an XmlReader according to the settings and parser context for parsing XML from the given TextReader. Create(TextReader input, XmlReaderSettings settings, XmlParserContext inputContext)1829 public static XmlReader Create(TextReader input, XmlReaderSettings settings, XmlParserContext inputContext) 1830 { 1831 if (settings == null) 1832 { 1833 settings = new XmlReaderSettings(); 1834 } 1835 return settings.CreateReader(input, string.Empty, inputContext); 1836 } 1837 1838 // Creates an XmlReader according to the settings wrapped over the given reader. Create(XmlReader reader, XmlReaderSettings settings)1839 public static XmlReader Create(XmlReader reader, XmlReaderSettings settings) 1840 { 1841 if (settings == null) 1842 { 1843 settings = new XmlReaderSettings(); 1844 } 1845 return settings.CreateReader(reader); 1846 } 1847 1848 // !!!!!! 1849 // NOTE: This method is called via reflection from System.Data.dll and from Analysis Services in Yukon. 1850 // Do not change its signature without notifying the appropriate teams! 1851 // !!!!!! 1852 #if UAPAOT CreateSqlReader(Stream input, XmlReaderSettings settings, XmlParserContext inputContext)1853 public static XmlReader CreateSqlReader(Stream input, XmlReaderSettings settings, XmlParserContext inputContext) 1854 #else 1855 internal static XmlReader CreateSqlReader(Stream input, XmlReaderSettings settings, XmlParserContext inputContext) 1856 #endif 1857 { 1858 if (input == null) 1859 { 1860 throw new ArgumentNullException(nameof(input)); 1861 } 1862 if (settings == null) 1863 { 1864 settings = new XmlReaderSettings(); 1865 } 1866 1867 XmlReader reader; 1868 1869 // allocate byte buffer 1870 byte[] bytes = new byte[CalcBufferSize(input)]; 1871 1872 int byteCount = 0; 1873 int read; 1874 do 1875 { 1876 read = input.Read(bytes, byteCount, bytes.Length - byteCount); 1877 byteCount += read; 1878 } while (read > 0 && byteCount< 2); 1879 1880 // create text or binary XML reader depenting on the stream first 2 bytes 1881 if (byteCount >= 2 && (bytes[0] == 0xdf && bytes[1] == 0xff)) 1882 { 1883 if (inputContext != null) 1884 throw new ArgumentException(SR.XmlBinary_NoParserContext, nameof(inputContext)); 1885 reader = new XmlSqlBinaryReader(input, bytes, byteCount, string.Empty, settings.CloseInput, settings); 1886 } 1887 else 1888 { 1889 reader = new XmlTextReaderImpl(input, bytes, byteCount, settings, null, string.Empty, inputContext, settings.CloseInput); 1890 } 1891 1892 // wrap with validating reader 1893 if (settings.ValidationType != ValidationType.None) 1894 { 1895 reader = settings.AddValidation(reader); 1896 } 1897 1898 if (settings.Async) 1899 { 1900 reader = XmlAsyncCheckReader.CreateAsyncCheckWrapper(reader); 1901 } 1902 1903 return reader; 1904 } 1905 CalcBufferSize(Stream input)1906 internal static int CalcBufferSize(Stream input) 1907 { 1908 // determine the size of byte buffer 1909 int bufferSize = DefaultBufferSize; 1910 if (input.CanSeek) 1911 { 1912 long len = input.Length; 1913 if (len < bufferSize) 1914 { 1915 bufferSize = checked((int)len); 1916 } 1917 else if (len > MaxStreamLengthForDefaultBufferSize) 1918 { 1919 bufferSize = BiggerBufferSize; 1920 } 1921 } 1922 1923 // return the byte buffer size 1924 return bufferSize; 1925 } 1926 1927 private object debuggerDisplayProxy { get { return new XmlReaderDebuggerDisplayProxy(this); } } 1928 1929 [DebuggerDisplay("{ToString()}")] 1930 private struct XmlReaderDebuggerDisplayProxy 1931 { 1932 private XmlReader _reader; 1933 XmlReaderDebuggerDisplayProxySystem.Xml.XmlReader.XmlReaderDebuggerDisplayProxy1934 internal XmlReaderDebuggerDisplayProxy(XmlReader reader) 1935 { 1936 _reader = reader; 1937 } 1938 ToStringSystem.Xml.XmlReader.XmlReaderDebuggerDisplayProxy1939 public override string ToString() 1940 { 1941 XmlNodeType nt = _reader.NodeType; 1942 string result = nt.ToString(); 1943 switch (nt) 1944 { 1945 case XmlNodeType.Element: 1946 case XmlNodeType.EndElement: 1947 case XmlNodeType.EntityReference: 1948 case XmlNodeType.EndEntity: 1949 result += ", Name=\"" + _reader.Name + '"'; 1950 break; 1951 case XmlNodeType.Attribute: 1952 case XmlNodeType.ProcessingInstruction: 1953 result += ", Name=\"" + _reader.Name + "\", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay(_reader.Value) + '"'; 1954 break; 1955 case XmlNodeType.Text: 1956 case XmlNodeType.Whitespace: 1957 case XmlNodeType.SignificantWhitespace: 1958 case XmlNodeType.Comment: 1959 case XmlNodeType.XmlDeclaration: 1960 case XmlNodeType.CDATA: 1961 result += ", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay(_reader.Value) + '"'; 1962 break; 1963 case XmlNodeType.DocumentType: 1964 result += ", Name=\"" + _reader.Name + "'"; 1965 result += ", SYSTEM=\"" + _reader.GetAttribute("SYSTEM") + '"'; 1966 result += ", PUBLIC=\"" + _reader.GetAttribute("PUBLIC") + '"'; 1967 result += ", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay(_reader.Value) + '"'; 1968 break; 1969 } 1970 return result; 1971 } 1972 } 1973 } 1974 } 1975 1976