다음을 통해 공유


System.Xml.XmlReader 클래스

이 문서에서는 이 API에 대한 참조 설명서에 대한 추가 설명서를 제공합니다.

XmlReader 는 문서 또는 스트림의 XML 데이터에 대한 전달 전용 읽기 전용 액세스를 제공합니다. 이 클래스는 W3C XML(Extensible Markup Language) 1.0(네 번째 버전)XML 1.0(세 번째 버전) 권장 사항의 네임스페이 스를 준수합니다.

XmlReader 메서드를 사용하면 XML 데이터를 통해 이동하고 노드의 내용을 읽을 수 있습니다. 클래스의 속성은 판독기의 위치인 현재 노드의 값을 반영합니다. 속성 값은 ReadState XML 판독기의 현재 상태를 나타냅니다. 예를 들어 속성은 메서드 및 ReadState.Closed 메서드에 XmlReader.Read 의해 설정 ReadState.Initial 됩니다XmlReader.Close. XmlReader또한 DTD 또는 스키마에 대한 데이터 규칙 검사 및 유효성 검사를 제공합니다.

XmlReader 는 끌어오기 모델을 사용하여 데이터를 검색합니다. 이 모델:

  • 자연스러운 하향식 절차적 구체화를 통해 상태 관리를 간소화합니다.
  • 여러 입력 스트림 및 계층을 지원합니다.
  • 클라이언트에서 문자열이 직접 기록되는 버퍼를 파서에 제공할 수 있으므로 추가 문자열 복사가 필요 없습니다.
  • 선택적 처리를 지원합니다. 클라이언트 항목을 건너뛰고 애플리케이션에 관심 있는 것을 처리 합니다. XML 스트림이 처리되는 방법(예: 정규화)을 관리하기 위해 속성을 미리 설정할 수도 있습니다.

XML 판독기 만들기

메서드를 Create 사용하여 인스턴스를 만듭니다 XmlReader .

.NET은 클래스(예: XmlTextReader, XmlNodeReaderXmlValidatingReader 클래스)의 XmlReader 구체적인 구현을 제공하지만 이러한 시나리오에서만 특수 클래스를 사용하는 것이 좋습니다.

  • 개체에서 XML DOM 하위 트리를 XmlNode 읽으려면 클래스를 XmlNodeReader 사용합니다. 그러나 이 클래스는 DTD 또는 스키마 유효성 검사를 지원하지 않습니다.
  • 요청 시 엔터티를 확장해야 하는 경우 텍스트 콘텐츠를 정규화하지 않거나 기본 특성이 반환되지 않도록 하려면 클래스를 XmlTextReader 사용합니다.

XML 판독기에서 사용하도록 설정할 기능 집합을 지정하려면 개체를 System.Xml.XmlReaderSettings 메서드에 Create 전달합니다. 단일 System.Xml.XmlReaderSettings 개체를 사용하여 동일한 기능을 사용하여 여러 판독기를 만들거나 개체를 System.Xml.XmlReaderSettings 수정하여 다른 기능 집합으로 새 판독기를 만들 수 있습니다. 기존 판독기에도 기능을 쉽게 추가할 수 있습니다.

개체를 System.Xml.XmlReaderSettings 사용하지 않는 경우 기본 설정이 사용됩니다. Create 자세한 내용은 참조 페이지를 참조하세요.

XmlReaderXmlException XML 구문 분석 오류를 throw합니다. 예외가 throw되면 판독기의 상태를 예측할 수 없습니다. 예를 들어 보고된 노드 형식은 현재 노드의 실제 노드 형식과 다를 수 있습니다. 이 속성을 사용하여 판독기가 ReadState 오류 상태인지 여부를 검사.

XML 데이터 유효성 검사

XML 문서의 구조와 해당 요소 관계, 데이터 형식 및 콘텐츠 제약 조건을 정의하려면 DTD(문서 형식 정의) 또는 XSD(XML 스키마 정의 언어) 스키마를 사용합니다. XML 문서는 W3C XML 1.0 권장 사항으로 정의된 모든 구문 요구 사항을 충족하는 경우 올바른 형식으로 간주됩니다. 올바른 형식이고 DTD 또는 스키마에서 정의한 제약 조건을 준수하는 경우 유효한 것으로 간주됩니다. (다음을 참조하세요. W3C XML 스키마 1부: 구조 체 및 W3C XML 스키마 파트 2: 데이터 형식 권장 사항.) 따라서 모든 유효한 XML 문서가 올바른 형식이지만 잘 구성된 모든 XML 문서가 유효하지는 않습니다.

DTD, 인라인 XSD 스키마 또는 개체(캐시)에 저장된 XSD 스키마에 XmlSchemaSet 대해 데이터의 유효성을 검사할 수 있습니다. 이러한 시나리오는 참조 페이지에 설명되어 Create 있습니다. XmlReader 에서는 XDR(XML-Data Reduced) 스키마 유효성 검사를 지원하지 않습니다.

클래스에서 XmlReaderSettings 다음 설정을 사용하여 인스턴스가 지원하는 유효성 검사 유형(있는 경우)을 XmlReader 지정합니다.

XmlReaderSettings 멤버 사용 지정할 함수
DtdProcessing 속성 DTD 처리를 허용할지 여부입니다. 기본값은 DTD 처리를 허용하지 않는 것입니다.
ValidationType 속성 판독기가 데이터의 유효성을 검사해야 하는지 여부와 수행할 유효성 검사 유형(DTD 또는 스키마)입니다. 기본값은 데이터 유효성 검사가 아닙니다.
ValidationEventHandler 이벤트 유효성 검사 이벤트에 대한 정보를 수신하기 위한 이벤트 처리기입니다. 이벤트 처리기가 제공되지 XmlException 않으면 첫 번째 유효성 검사 오류가 발생합니다.
ValidationFlags 속성 열거형 멤버를 XmlSchemaValidationFlags 통한 추가 유효성 검사 옵션:

- AllowXmlAttributes-- 스키마에 정의되지 않은 경우에도 인스턴스 문서에서 XML 특성(xml:*)을 허용합니다. 특성은 해당 데이터 형식에 따라 유효성을 검사합니다. XmlSchemaValidationFlags 특정 시나리오에서 사용할 설정에 대한 참조 페이지를 참조하세요. (기본적으로 사용 안 함)
- ProcessIdentityConstraints--Process IDENTITY 제약 조건 (xs:ID, , xs:keyxs:IDREF, xs:keyref, xs:unique) 유효성 검사 하는 동안 발생 합니다. (기본적으로 사용하도록 설정됩니다.)
- ProcessSchemaLocation --process schemas specified by the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute. (기본적으로 사용하도록 설정됩니다.)
- ProcessInlineSchema-- 유효성 검사 중에 인라인 XML 스키마를 처리합니다. (기본적으로 사용 안 함)
- ReportValidationWarnings--유효성 검사 경고가 발생하면 이벤트를 보고합니다. 일반적으로 특정 요소 또는 특성의 유효성을 검사할 DTD 또는 XML 스키마가 없는 경우 경고가 발생합니다. 알림 ValidationEventHandler 에 사용됩니다. (기본적으로 사용 안 함)
Schemas 유효성 검사에 사용할 XmlSchemaSet입니다.
XmlResolver 속성 XmlResolver 외부 리소스를 확인하고 액세스하기 위한 것입니다. 여기에는 DTD 및 스키마와 같은 외부 엔터티와 XML 스키마에 포함된 모든 xs:include 요소 또는 xs:import 요소가 포함될 수 있습니다. 지정 XmlResolverXmlReader 하지 않으면 사용자 자격 증명이 없는 기본값 XmlUrlResolver 을 사용합니다.

데이터 규칙

메서드에서 Create 만든 XML 판독기는 기본적으로 다음과 같은 규정 준수 요구 사항을 충족합니다.

  • W3C XML 1.0 권장 사항에 따라 새 줄과 특성 값이 정규화됩니다.

  • 모든 엔터티는 자동으로 확장됩니다.

  • 문서 형식 정의에 선언된 기본 특성은 판독기에서 유효성을 검사하지 않는 경우에도 항상 추가됩니다.

  • 올바른 XML 네임스페이스 URI에 매핑된 XML 접두사 선언이 허용됩니다.

  • 단일 특성 선언 및 NmTokens 단일 NotationTypeEnumeration 특성 선언의 표기법 이름은 고유합니다.

다음 XmlReaderSettings 속성을 사용하여 사용하도록 설정할 규칙 검사 유형을 지정합니다.

XmlReaderSettings 속성 사용 To 기본값
CheckCharacters 속성 다음에 대해 검사 사용하거나 사용하지 않도록 설정합니다.

- W3C XML 1.0 권장 사항의 2.2자 섹션에 정의된 대로 문자는 법적 XML 문자 범위 내에 있습니다.
- 모든 XML 이름은 W3C XML 1.0 권장 사항의 2.3 공통 구문 구문 섹션에 정의된 대로 유효합니다 .

이 속성이 (기본값)XmlException로 설정 true 되면 XML 파일에 잘못된 문자 또는 잘못된 XML 이름이 포함된 경우 예외가 throw됩니다(예: 요소 이름은 숫자로 시작).
문자 및 이름 검사 사용하도록 설정됩니다.

문자 엔터티 참조에 false 대한 문자 검사 해제하도록 설정합니다CheckCharacters. 판독기에서 텍스트 데이터를 처리하는 경우 이 설정에 관계없이 XML 이름이 유효한지 항상 검사. 참고: XML 1.0 권장 사항에는 DTD가 있을 때 문서 수준 준수가 필요합니다. 따라서 판독기를 지원 ConformanceLevel.Fragment하도록 구성되었지만 XML 데이터에 DTD(문서 형식 정의)가 포함되어 있으면 throw XmlException 됩니다.
ConformanceLevel 속성 적용할 규칙 수준을 선택합니다.

- Document. 올바른 형식의 XML 1.0 문서에 대한 규칙을 준수합니다.
- Fragment. 외부 구문 분석된 엔터티로 사용할 수 있는 잘 구성된 문서 조각에 대한 규칙을 준수합니다.
- Auto. 판독기에서 결정한 수준을 준수합니다.

데이터가 일치하지 않으면 예외가 XmlException throw됩니다.
Document

현재 노드는 XML 판독기를 현재 배치하는 XML 노드입니다. 모든 XmlReader 메서드는 이 노드와 관련하여 작업을 수행하고 모든 XmlReader 속성은 현재 노드의 값을 반영합니다.

다음 메서드를 사용하면 노드를 쉽게 탐색하고 데이터를 구문 분석할 수 있습니다.

XmlReaderSettings 메서드 사용 To
Read 첫 번째 노드를 읽고 한 번에 하나의 노드 스트림을 진행합니다. 이러한 호출은 일반적으로 루프 내에서 while 수행됩니다.

NodeType 속성을 사용하여 현재 노드의 형식(예: 특성, 주석, 요소 등)을 가져옵니다.
Skip 현재 노드의 자식을 건너뛰고 다음 노드로 이동합니다.
MoveToContentMoveToContentAsync 비컨텐트 노드를 건너뛰고 다음 콘텐츠 노드 또는 파일의 끝으로 이동합니다.

비컨텐트 노드에는 ProcessingInstruction, DocumentType, CommentWhitespaceSignificantWhitespace.

콘텐츠 노드에는 공백이 아닌 텍스트, CDATAEntityReferenceEndEntity.
ReadSubtree 요소와 해당 자식을 모두 읽고 새 XmlReader 인스턴스를 로 설정한 상태로 반환합니다 ReadState.Initial.

이 메서드는 XML 요소 주위에 경계를 만드는 데 유용합니다. 예를 들어 처리를 위해 다른 구성 요소에 데이터를 전달하고 구성 요소에서 액세스할 수 있는 데이터의 양을 제한하려는 경우입니다.

XmlReader.Read 한 번에 한 노드씩 텍스트 스트림을 탐색하고 각 노드의 형식을 표시하는 예제는 참조 페이지를 참조하세요.

다음 섹션에서는 요소, 특성 및 형식화된 데이터와 같은 특정 형식의 데이터를 읽는 방법을 설명합니다.

XML 요소 읽기

다음 표에서는 클래스가 요소 처리를 위해 제공하는 메서드 및 속성을 XmlReader 나열합니다. 요소에 XmlReader 배치된 후 노드 속성(예: Name)은 요소 값을 반영합니다. 아래에 설명된 멤버 외에도 클래스의 일반적인 메서드 및 속성을 XmlReader 사용하여 요소를 처리할 수도 있습니다. 예를 들어 메서드를 ReadInnerXml 사용하여 요소의 내용을 읽을 수 있습니다.

참고 항목

시작 태그, 끝 태그 및 빈 요소 태그의 정의는 W3C XML 1.0 권장 사항 의 섹션 3.1을 참조하세요.

XmlReader 멤버 사용 To
IsStartElement 메서드 현재 노드가 시작 태그인지 빈 요소 태그인지 확인합니다.
ReadStartElement 메서드 현재 노드가 요소인지 확인하고 판독기를 다음 노드(호출 IsStartElement 뒤에 오는 Read)로 이동합니다.
ReadEndElement 메서드 현재 노드가 끝 태그인지 확인하고 판독기를 다음 노드로 진행합니다.
ReadElementString 메서드 텍스트 전용 요소를 읽습니다.
ReadToDescendant 메서드 XML 판독기를 지정된 이름의 다음 하위 요소(자식) 요소로 이동합니다.
ReadToNextSibling 메서드 XML 판독기를 지정된 이름을 포함하는 다음 형제 요소로 진행합니다.
IsEmptyElement 속성 현재 요소에 끝 요소 태그가 있는지 확인합니다. 예시:

- <item num="123"/> (isIsEmptyElementtrue.)
- <item num="123"> </item> (IsEmptyElementfalse요소의 콘텐츠가 비어 있지만)입니다.

요소의 텍스트 내용을 읽는 예제는 메서드를 참조하세요 ReadString . 다음 예제에서는 루프를 사용하여 요소를 처리합니다 while .

while (reader.Read()) {
  if (reader.IsStartElement()) {
    if (reader.IsEmptyElement)
                {
                    Console.WriteLine("<{0}/>", reader.Name);
                }
                else {
      Console.Write("<{0}> ", reader.Name);
      reader.Read(); // Read the start tag.
      if (reader.IsStartElement())  // Handle nested elements.
        Console.Write("\r\n<{0}>", reader.Name);
      Console.WriteLine(reader.ReadString());  //Read the text content of the element.
    }
  }
}
While reader.Read()
  If reader.IsStartElement() Then
    If reader.IsEmptyElement Then
      Console.WriteLine("<{0}/>", reader.Name)
    Else
      Console.Write("<{0}> ", reader.Name)
      reader.Read() ' Read the start tag.
      If reader.IsStartElement() Then ' Handle nested elements.
        Console.Write(vbCr + vbLf + "<{0}>", reader.Name)
      End If
      Console.WriteLine(reader.ReadString()) 'Read the text content of the element.
    End If
  End If
End While

XML 특성 읽기

XML 특성은 요소에서 가장 일반적으로 찾을 수 있지만 XML 선언 및 문서 형식 노드에서도 허용됩니다.

요소 노드에 배치된 경우 메서드를 MoveToAttribute 사용하여 요소의 특성 목록을 탐색할 수 있습니다. 호출된 후에 MoveToAttribute 는 특성이 속한 요소의 속성이 아니라 , NamespaceURIPrefix 등의 Name노드 속성이 해당 특성의 속성을 반영합니다.

클래스는 XmlReader 요소의 특성을 읽고 처리하는 데 이러한 메서드와 속성을 제공합니다.

XmlReader 멤버 사용 To
HasAttributes 속성 현재 노드에 특성이 있는지 확인합니다.
AttributeCount 속성 현재 요소의 특성 수를 가져옵니다.
MoveToFirstAttribute 메서드 요소의 첫 번째 특성으로 이동합니다.
MoveToNextAttribute 메서드 요소의 다음 특성으로 이동합니다.
MoveToAttribute 메서드 지정된 특성으로 이동합니다.
GetAttribute 메서드 또는 Item[] 속성 지정된 특성의 값을 가져옵니다.
IsDefault 속성 현재 노드가 DTD 또는 스키마에 정의된 기본값에서 생성된 특성인지 확인합니다.
MoveToElement 메서드 현재 특성을 소유하는 요소로 이동합니다. 특성을 탐색한 후 요소로 돌아가려면 이 메서드를 사용합니다.
ReadAttributeValue 메서드 특성 값을 하나 이상의 TextEntityReference노드 또는 EndEntity 노드로 구문 분석합니다.

일반 XmlReader 메서드 및 속성을 사용하여 특성을 처리할 수도 있습니다. 예를 들어 특성 NameXmlReader 배치된 후 속성과 Value 속성은 특성의 값을 반영합니다. 콘텐츠 Read 메서드를 사용하여 특성 값을 가져올 수도 있습니다.

이 예제에서는 속성을 사용하여 AttributeCount 요소의 모든 특성을 탐색합니다.

// Display all attributes.
if (reader.HasAttributes) {
  Console.WriteLine("Attributes of <" + reader.Name + ">");
  for (int i = 0; i < reader.AttributeCount; i++) {
    Console.WriteLine("  {0}", reader[i]);
  }
  // Move the reader back to the element node.
  reader.MoveToElement();
}
' Display all attributes.
If reader.HasAttributes Then
  Console.WriteLine("Attributes of <" + reader.Name + ">")
  Dim i As Integer
  For i = 0 To (reader.AttributeCount - 1)
    Console.WriteLine("  {0}", reader(i))
  Next i
  ' Move the reader back to the element node.
  reader.MoveToElement() 
End If

이 예제에서는 루프의 MoveToNextAttribute 메서드를 while 사용하여 특성을 탐색합니다.

if (reader.HasAttributes) {
  Console.WriteLine("Attributes of <" + reader.Name + ">");
  while (reader.MoveToNextAttribute()) {
    Console.WriteLine(" {0}={1}", reader.Name, reader.Value);
  }
  // Move the reader back to the element node.
  reader.MoveToElement();
}
If reader.HasAttributes Then
  Console.WriteLine("Attributes of <" + reader.Name + ">")
  While reader.MoveToNextAttribute()
    Console.WriteLine(" {0}={1}", reader.Name, reader.Value)
  End While
  ' Move the reader back to the element node.
  reader.MoveToElement()
End If

XML 선언 노드에서 특성 읽기

XML 판독기를 XML 선언 노드 Value 에 배치하면 속성은 버전, 독립 실행형 및 인코딩 정보를 단일 문자열로 반환합니다. XmlReader메서드, XmlTextReader 클래스 및 클래스에서 Create 만든 개체는 XmlValidatingReader 버전, 독립 실행형 및 인코딩 항목을 특성으로 노출합니다.

문서 형식 노드에서 특성 읽기

XML 판독기를 문서 형식 노드 GetAttribute 에 배치할 때 메서드와 속성을 사용하여 SYSTEM 및 Item[] PUBLIC 리터럴의 값을 반환할 수 있습니다. 예를 들어 호출 reader.GetAttribute("PUBLIC") 은 PUBLIC 값을 반환합니다.

명령 노드 처리에 대한 특성 읽기

XmlReader 처리 명령 노드에 위치하면 속성은 Value 전체 텍스트 콘텐츠를 반환합니다. 처리 명령 노드의 항목은 특성으로 처리되지 않습니다. 또는 MoveToAttribute 메서드를 사용하여 GetAttribute 읽을 수 없습니다.

XML 콘텐츠 읽기

XmlReader 클래스에는 XML 파일에서 콘텐츠를 읽고 콘텐츠를 문자열 값으로 반환하는 다음 멤버가 포함됩니다. (CLR 형식을 반환하려면 다음을 참조하세요 .CLR 형식으로 변환합니다.)

XmlReader 멤버 사용 To
Value 속성 현재 노드의 텍스트 콘텐츠를 가져옵니다. 반환되는 값은 노드 유형에 따라 달라집니다. Value 자세한 내용은 참조 페이지를 참조하세요.
ReadString 메서드 요소 또는 텍스트 노드의 콘텐츠를 문자열로 가져옵니다. 이 메서드는 명령 및 주석 처리를 중지합니다.

이 메서드가 특정 노드 형식을 처리하는 방법에 대한 자세한 내용은 참조 페이지를 참조 ReadString 하세요.
ReadInnerXmlReadInnerXmlAsync 메서드 태그를 포함하여 현재 노드의 모든 콘텐츠를 가져옵니다. 시작 태그와 끝 태그는 제외됩니다. 예를 들면 다음과 같습니다.

<node>this<child id="123"/></node>

ReadInnerXml은 다음을 반환합니다.

this<child id="123"/>
ReadOuterXmlReadOuterXmlAsync 메서드 태그 및 시작/끝 태그를 포함하여 현재 노드 및 해당 자식의 모든 콘텐츠를 가져옵니다. 예를 들면 다음과 같습니다.

<node>this<child id="123"/></node>

ReadOuterXml은 다음을 반환합니다.

<node>this<child id="123"/></node>

CLR 형식으로 변환

다음 표에 나열된 클래스의 XmlReader 멤버를 사용하여 XML 데이터를 읽고 값을 문자열 대신 CLR(공용 언어 런타임) 형식으로 반환할 수 있습니다. 이러한 멤버를 사용하면 문자열 값을 수동으로 구문 분석하거나 변환하지 않고도 코딩 작업에 가장 적합한 표현의 값을 가져올 수 있습니다.

  • ReadElementContentAs 메서드는 요소 노드 형식에서만 호출할 수 있습니다. 이러한 메서드는 자식 요소 또는 혼합 콘텐츠가 포함된 요소에서 사용할 수 없습니다. 호출되면 개체는 XmlReader 시작 태그를 읽고 요소 콘텐츠를 읽은 다음 끝 요소 태그를 지나 이동합니다. 처리 지침 및 주석이 무시되고 엔터티가 확장됩니다.

  • ReadContentAs 메서드는 현재 판독기 위치에서 텍스트 콘텐츠를 읽고 XML 데이터에 연결된 스키마 또는 데이터 형식 정보가 없는 경우 텍스트 콘텐츠를 요청된 반환 형식으로 변환합니다. 텍스트, 공백, 상당한 공백 및 CDATA 섹션이 연결됩니다. 주석 및 처리 지침은 건너뛰고 엔터티 참조는 자동으로 해결됩니다.

클래스는 XmlReader W3C XML 스키마 파트 2: 데이터 형식 권장 사항에 정의된 규칙을 사용합니다.

XmlReader 메서드 사용 이 CLR 형식을 반환하려면
ReadContentAsBooleanReadElementContentAsBoolean Boolean
ReadContentAsDateTimeReadElementContentAsDateTime DateTime
ReadContentAsDoubleReadElementContentAsDouble Double
ReadContentAsLongReadElementContentAsLong Int64
ReadContentAsIntReadElementContentAsInt Int32
ReadContentAsStringReadElementContentAsString String
ReadContentAsReadElementContentAs 매개 변수를 사용하여 지정하는 returnType 형식
ReadContentAsObjectReadElementContentAsObject 속성에 지정된 가장 적합한 형식입니다 XmlReader.ValueType . 매핑 정보는 System.Xml 클래스의 형식 지원을 참조하세요.

형식 때문에 요소를 CLR 형식으로 쉽게 변환할 수 없는 경우 스키마 매핑을 사용하여 성공적인 변환을 보장할 수 있습니다. 다음 예제에서는 .xsd 파일을 사용하여 요소를 형식으로 xs:date 변환 hire-date 한 다음 메서드를 ReadElementContentAsDateTime 사용하여 요소를 개체로 DateTime 반환합니다.

입력(hireDate.xml):

<employee xmlns="urn:empl-hire">
    <ID>12365</ID>
    <hire-date>2003-01-08</hire-date>
    <title>Accountant</title>
</employee>

스키마(hireDate.xsd):

<?xml version="1.0"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="urn:empl-hire" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="employee">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="ID" type="xs:unsignedShort" />
        <xs:element name="hire-date" type="xs:date" />
        <xs:element name="title" type="xs:string" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

코드:

// Create a validating XmlReader object. The schema
// provides the necessary type information.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add("urn:empl-hire", "hireDate.xsd");
using (XmlReader reader = XmlReader.Create("hireDate.xml", settings)) {

  // Move to the hire-date element.
  reader.MoveToContent();
  reader.ReadToDescendant("hire-date");

  // Return the hire-date as a DateTime object.
  DateTime hireDate = reader.ReadElementContentAsDateTime();
  Console.WriteLine("Six Month Review Date: {0}", hireDate.AddMonths(6));
}
' Create a validating XmlReader object. The schema 
' provides the necessary type information.
Dim settings As XmlReaderSettings = New XmlReaderSettings()
settings.ValidationType = ValidationType.Schema
settings.Schemas.Add("urn:empl-hire", "hireDate.xsd")
Using reader As XmlReader = XmlReader.Create("hireDate.xml", settings) 
  ' Move to the hire-date element.
  reader.MoveToContent()
  reader.ReadToDescendant("hire-date")

  ' Return the hire-date as a DateTime object.
  Dim hireDate As DateTime = reader.ReadElementContentAsDateTime()
  Console.WriteLine("Six Month Review Date: {0}", hireDate.AddMonths(6))
End Using

출력:

Six Month Review Date:  7/8/2003 12:00:00 AM

비동기 프로그래밍

XmlReader 대부분의 메서드에는 메서드 이름의 끝에 "Async"가 있는 비동기 대응 항목이 있습니다. 예를 들어 해당하는 비동기 값은 .입니다 ReadContentAsObjectReadContentAsObjectAsync.

다음 메서드는 비동기 메서드 호출과 함께 사용할 수 있습니다.

다음 섹션에서는 비동기 항목이 없는 메서드에 대한 비동기 사용을 설명합니다.

ReadStartElement 메서드

public static async Task ReadStartElementAsync(this XmlReader reader, string localname, string ns)
{
    if (await reader.MoveToContentAsync() != XmlNodeType.Element)
    {
        throw new InvalidOperationException(reader.NodeType.ToString() + " is an invalid XmlNodeType");
    }
    if ((reader.LocalName == localname) && (reader.NamespaceURI == ns))
    {
        await reader.ReadAsync();
    }
    else
    {
        throw new InvalidOperationException("localName or namespace doesn’t match");
    }
}
<Extension()>
Public Async Function ReadStartElementAsync(reader As XmlReader, localname As String, ns As String) As Task
    If (Await reader.MoveToContentAsync() <> XmlNodeType.Element) Then
        Throw New InvalidOperationException(reader.NodeType.ToString() + " is an invalid XmlNodeType")
    End If

    If ((reader.LocalName = localname) And (reader.NamespaceURI = ns)) Then
        Await reader.ReadAsync()
    Else
        Throw New InvalidOperationException("localName or namespace doesn’t match")
    End If
End Function

ReadEndElement 메서드

public static async Task ReadEndElementAsync(this XmlReader reader)
{
    if (await reader.MoveToContentAsync() != XmlNodeType.EndElement)
    {
        throw new InvalidOperationException();
    }
    await reader.ReadAsync();
}
<Extension()>
Public Async Function ReadEndElementAsync(reader As XmlReader) As task
    If (Await reader.MoveToContentAsync() <> XmlNodeType.EndElement) Then
        Throw New InvalidOperationException()
    End If
    Await reader.ReadAsync()
End Function

ReadToNextSibling 메서드

public static async Task<bool> ReadToNextSiblingAsync(this XmlReader reader, string localName, string namespaceURI)
{
    if (localName == null || localName.Length == 0)
    {
        throw new ArgumentException("localName is empty or null");
    }
    if (namespaceURI == null)
    {
        throw new ArgumentNullException("namespaceURI");
    }

    // atomize local name and namespace
    localName = reader.NameTable.Add(localName);
    namespaceURI = reader.NameTable.Add(namespaceURI);

    // find the next sibling
    XmlNodeType nt;
    do
    {
        await reader.SkipAsync();
        if (reader.ReadState != ReadState.Interactive)
            break;
        nt = reader.NodeType;
        if (nt == XmlNodeType.Element &&
             ((object)localName == (object)reader.LocalName) &&
             ((object)namespaceURI ==(object)reader.NamespaceURI))
        {
            return true;
        }
    } while (nt != XmlNodeType.EndElement && !reader.EOF);
    
    return false;
}
<Extension()>
Public Async Function ReadToNextSiblingAsync(reader As XmlReader, localName As String, namespaceURI As String) As Task(Of Boolean)
    If (localName = Nothing Or localName.Length = 0) Then
        Throw New ArgumentException("localName is empty or null")
    End If

    If (namespaceURI = Nothing) Then
        Throw New ArgumentNullException("namespaceURI")
    End If

    ' atomize local name and namespace
    localName = reader.NameTable.Add(localName)
    namespaceURI = reader.NameTable.Add(namespaceURI)

    ' find the next sibling
    Dim nt As XmlNodeType
    Do

        Await reader.SkipAsync()
        If (reader.ReadState <> ReadState.Interactive) Then
            Exit Do
        End If
        nt = reader.NodeType
        If ((nt = XmlNodeType.Element) And
           ((CObj(localName) = CObj(reader.LocalName))) And
           (CObj(namespaceURI) = CObj(reader.NamespaceURI))) Then
            Return True
        End If
    Loop While (nt <> XmlNodeType.EndElement And (Not reader.EOF))

    Return False

End Function

ReadToFollowing 메서드

public static async Task<bool> ReadToFollowingAsync(this XmlReader reader, string localName, string namespaceURI)
{
    if (localName == null || localName.Length == 0)
    {
        throw new ArgumentException("localName is empty or null");
    }
    if (namespaceURI == null)
    {
        throw new ArgumentNullException("namespaceURI");
    }

    // atomize local name and namespace
    localName = reader.NameTable.Add(localName);
    namespaceURI = reader.NameTable.Add(namespaceURI);

    // find element with that name
    while (await reader.ReadAsync())
    {
        if (reader.NodeType == XmlNodeType.Element && ((object)localName == (object)reader.LocalName) && ((object)namespaceURI == (object)reader.NamespaceURI))
        {
            return true;
        }
    }
    return false;
}
<Extension()>
Public Async Function ReadToFollowingAsync(reader As XmlReader, localName As String, namespaceURI As String) As Task(Of Boolean)
    If (localName = Nothing Or localName.Length = 0) Then
        Throw New ArgumentException("localName is empty or null")
    End If

    If (namespaceURI = Nothing) Then
        Throw New ArgumentNullException("namespaceURI")
    End If

    ' atomize local name and namespace
    localName = reader.NameTable.Add(localName)
    namespaceURI = reader.NameTable.Add(namespaceURI)

    ' find element with that name
    While (Await reader.ReadAsync())
        If ((reader.NodeType = XmlNodeType.Element) And
           (CObj(localName) = CObj(reader.LocalName)) And
           (CObj(namespaceURI) = CObj(reader.NamespaceURI))) Then
            Return True
        End If
    End While

    Return False
End Function

ReadToDescendant 메서드

public static async Task<bool> ReadToDescendantAsync(this XmlReader reader, string localName, string namespaceURI)
{
    if (localName == null || localName.Length == 0)
    {
        throw new ArgumentException("localName is empty or null");
    }
    if (namespaceURI == null)
    {
        throw new ArgumentNullException("namespaceURI");
    }
    // save the element or root depth
    int parentDepth = reader.Depth;
    if (reader.NodeType != XmlNodeType.Element)
    {
        // adjust the depth if we are on root node
        if (reader.ReadState == ReadState.Initial)
        {
            parentDepth--;
        }
        else
        {
            return false;
        }
    }
    else if (reader.IsEmptyElement)
    {
        return false;
    }

    // atomize local name and namespace
    localName = reader.NameTable.Add(localName);
    namespaceURI = reader.NameTable.Add(namespaceURI);

    // find the descendant
    while (await reader.ReadAsync() && reader.Depth > parentDepth)
    {
        if (reader.NodeType == XmlNodeType.Element && ((object)localName == (object)reader.LocalName) && ((object)namespaceURI == (object)reader.NamespaceURI))
        {
            return true;
        }
    }
    return false;
}
<Extension()>
Public Async Function ReadToDescendantAsync(reader As XmlReader, localName As String, namespaceURI As String) As Task(Of Boolean)
    If (localName = Nothing Or localName.Length = 0) Then
        Throw New ArgumentException("localName is empty or null")
    End If

    If (namespaceURI = Nothing) Then
        Throw New ArgumentNullException("namespaceURI")
    End If

    ' save the element or root depth
    Dim parentDepth As Integer = reader.Depth
    If (reader.NodeType <> XmlNodeType.Element) Then
        ' adjust the depth if we are on root node
        If (reader.ReadState = ReadState.Initial) Then
            parentDepth -= 1
        Else
            Return False
        End If
    ElseIf (reader.IsEmptyElement) Then
        Return False
    End If
    ' atomize local name and namespace
    localName = reader.NameTable.Add(localName)
    namespaceURI = reader.NameTable.Add(namespaceURI)

    ' find the descendant
    While (Await reader.ReadAsync() And reader.Depth > parentDepth)
        If (reader.NodeType = XmlNodeType.Element And
           (CObj(localName) = CObj(reader.LocalName)) And
           (CObj(namespaceURI) = CObj(reader.NamespaceURI))) Then
            Return True
        End If
    End While

    Return False
End Function

보안 고려 사항

클래스를 사용할 때 다음을 고려합니다 XmlReader .

  • 예외에서 throw된 예외는 앱에 XmlReader 버블링하지 않으려는 경로 정보를 공개할 수 있습니다. 앱은 예외를 catch하고 적절하게 처리해야 합니다.

  • 서비스 거부 문제가 우려되거나 신뢰할 수 없는 원본을 처리하는 경우 DTD 처리를 사용하도록 설정하지 마세요. DTD 처리는 메서드에서 만든 개체에 대해 XmlReader 기본적으로 사용하지 않도록 설정됩니다 Create .

    DTD 처리를 활성화하는 경우 XmlSecureResolver를 사용하여 XmlReader가 액세스할 수 있는 리소스를 제한할 수 있습니다. XML 처리가 메모리 및 시간이 제한되도록 앱을 디자인할 수도 있습니다. 예를 들어 ASP.NET 앱에서 제한 시간을 구성할 수 있습니다.

  • XML 데이터에는 스키마 파일과 같은 외부 리소스에 대한 참조가 포함될 수 있습니다. 기본적으로 외부 리소스는 사용자 자격 증명이 없는 개체를 XmlUrlResolver 사용하여 확인됩니다. 이러한 경우 다음 중 하나를 수행하여 보안을 강화할 수 있습니다.

  • ProcessInlineSchema 개체의 XmlReaderSettings 유효성 검사 플래그 및 ProcessSchemaLocation 유효성 검사는 기본적으로 설정되지 않습니다. 이렇게 하면 신뢰할 수 없는 원본에서 XML 데이터를 처리할 때 스키마 기반 공격으로부터 보호할 XmlReader 수 있습니다. 이 플래그를 설정하면 XmlResolver 개체의 XmlReaderSettings를 사용하여 XmlReader에서 인스턴스 문서에 나타난 스키마 위치를 확인할 수 있습니다. 속성이 XmlResolver 설정된 null경우 스키마 위치는 유효성 검사 플래그 및 ProcessSchemaLocation 유효성 검사 플래그가 ProcessInlineSchema 설정된 경우에도 확인되지 않습니다.

    문서의 유효성을 검사하는 동안 스키마를 추가하면 새 형식이 추가되고 해당 문서에 대한 유효성 검사 결과가 달라질 수 있습니다. 결과적으로 외부 스키마는 신뢰할 수 있는 소스에서만 확인해야 합니다.

    문서의 많은 부분에 대한 ID 제약 조건이 있는 스키마에 대해 고가용성 시나리오에서 신뢰할 수 없는 대형 XML 문서의 유효성을 검사할 때 플래그를 사용하지 않도록 설정하는 ProcessIdentityConstraints 것이 좋습니다. 이 플래그는 기본적으로 사용하도록 설정됩니다.

  • XML 데이터에는 처리하는 데 시간이 많이 걸리는 수많은 특성, 네임스페이스 선언, 중첩된 요소 등이 포함될 수 있습니다. 전송되는 입력의 크기를 제한하려면 다음을 XmlReader수행할 수 있습니다.

  • 이 메서드는 ReadValueChunk 큰 데이터 스트림을 처리하는 데 사용할 수 있습니다. 이 메서드는 전체 값에 대한 단일 문자열을 할당하는 대신 한 번에 적은 수의 문자를 읽습니다.

  • 고유한 로컬 이름, 네임스페이스 또는 접두사 수가 많은 XML 문서를 읽을 때 문제가 발생할 수 있습니다. 파생 XmlReader되는 클래스를 사용하고 각 항목에 LocalName대한 , Prefix또는 NamespaceURI 속성을 호출하는 경우 반환된 문자열이 에 NameTable추가됩니다. 절대 크기가 NameTable 감소하지 않는 컬렉션이 문자열 핸들의 가상 메모리 누수로 생성됩니다. 이에 대한 한 가지 완화 방법은 클래스에서 NameTable 파생되고 최대 크기 할당량을 적용하는 것입니다. (사용을 방지하거나 가득 찼을 NameTable때 전환할 수 있는 NameTable 방법은 없습니다). 또 다른 완화 방법은 멘션 속성을 사용하지 않고 가능한 경우 메서드와 함께 IsStartElement 메서드를 사용하는 MoveToAttribute 것입니다. 이러한 메서드는 문자열을 반환하지 않으므로 컬렉션이 과도하게 채워 NameTable 지는 문제를 방지합니다.

  • XmlReaderSettings 개체에는 사용자 자격 증명과 같은 중요한 정보가 포함될 수 있습니다. 신뢰할 수 없는 구성 요소는 개체와 사용자 자격 증명을 사용하여 XmlReaderSettings 데이터를 읽을 개체를 만들 XmlReader 수 있습니다. 개체를 캐싱 XmlReaderSettings 하거나 한 구성 요소에서 다른 구성 요소로 개체를 XmlReaderSettings 전달할 때는 주의해야 합니다.

  • 신뢰할 수 없는 소스로부터 NameTable, XmlNamespaceManagerXmlResolver 개체 등의 지원 구성 요소를 받지 마십시오.