System.Xml.XmlReader, klasa

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

XmlReader zapewnia dostęp tylko do odczytu do danych XML w dokumencie lub strumieniu. Ta klasa jest zgodna z zaleceniami języka W3C Extensible Markup Language (XML) 1.0 (czwarta wersja) i przestrzeniami nazw w języku XML 1.0 (trzecia wersja).

XmlReader metody umożliwiają przechodzenie przez dane XML i odczytywanie zawartości węzła. Właściwości klasy odzwierciedlają wartość bieżącego węzła, czyli miejsce, w którym znajduje się czytnik. Wartość ReadState właściwości wskazuje bieżący stan czytnika XML. Na przykład właściwość jest ustawiana na ReadState.Initial wartość przy użyciu XmlReader.Read metody i ReadState.Closed metody XmlReader.Close . XmlReader Zapewnia również sprawdzanie zgodności danych i walidację względem dtD lub schematu.

XmlReader używa modelu ściągania do pobierania danych. Ten model:

  • Upraszcza zarządzanie stanem przez naturalne, odgórne uściślenie proceduralne.
  • Obsługuje wiele strumieni wejściowych i warstw.
  • Umożliwia klientowi nadanie analizatorowi buforu, w którym ciąg jest zapisywany bezpośrednio, a tym samym unika konieczności dodatkowej kopii ciągu.
  • Obsługuje przetwarzanie selektywne. Klient może pominąć elementy i przetworzyć te, które są interesujące dla aplikacji. Można również ustawić właściwości z wyprzedzeniem, aby zarządzać sposobem przetwarzania strumienia XML (na przykład normalizacji).

Tworzenie czytnika XML

Create Użyj metody , aby utworzyć XmlReader wystąpienie.

Mimo że platforma .NET udostępnia konkretne implementacje XmlReader klasy, takie jak XmlTextReader, XmlNodeReaderi , i XmlValidatingReader , zalecamy używanie wyspecjalizowanych klas tylko w następujących scenariuszach:

  • Jeśli chcesz odczytać poddrzewo DOM XML z XmlNode obiektu, użyj XmlNodeReader klasy . (Jednak ta klasa nie obsługuje walidacji dtD ani schematu).
  • Jeśli musisz rozwinąć jednostki na żądanie, nie chcesz, aby zawartość tekstowa została znormalizowana lub nie chcesz zwracać atrybutów domyślnych, użyj XmlTextReader klasy .

Aby określić zestaw funkcji, które chcesz włączyć w czytniku XML, przekaż System.Xml.XmlReaderSettings obiekt do Create metody . Można użyć pojedynczego System.Xml.XmlReaderSettings obiektu do utworzenia wielu czytników z tą samą funkcjonalnością lub zmodyfikować System.Xml.XmlReaderSettings obiekt w celu utworzenia nowego czytnika z innym zestawem funkcji. Możesz również łatwo dodawać funkcje do istniejącego czytnika.

Jeśli nie używasz System.Xml.XmlReaderSettings obiektu, są używane ustawienia domyślne. Aby uzyskać szczegółowe informacje, zobacz stronę referencyjną Create .

XmlReader zgłasza błędy XmlException analizy XML. Po wystąpieniu wyjątku stan czytnika nie jest przewidywalny. Na przykład zgłoszony typ węzła może różnić się od rzeczywistego typu węzła bieżącego węzła. Użyj właściwości , ReadState aby sprawdzić, czy czytnik jest w stanie błędu.

Weryfikowanie danych XML

Aby zdefiniować strukturę dokumentu XML i jego relacji elementów, typów danych i ograniczeń zawartości, należy użyć schematu definicji typu dokumentu (DTD) lub języka definicji schematu XML (XSD). Dokument XML jest uznawany za dobrze sformułowany, jeśli spełnia wszystkie wymagania składniowe zdefiniowane przez zalecenie W3C XML 1.0. Jest on uznawany za prawidłowy, jeśli jest dobrze sformułowany, a także jest zgodny z ograniczeniami zdefiniowanymi przez jego dtD lub schemat. (Zobacz Schemat XML W3C — część 1: struktury i schemat XML W3C — część 2: zalecenia dotyczące typów danych). W związku z tym, mimo że wszystkie prawidłowe dokumenty XML są dobrze sformułowane, nie wszystkie poprawnie sformułowane dokumenty XML są prawidłowe.

Możesz zweryfikować dane względem dtD, wbudowanego schematu XSD lub schematu XSD przechowywanego XmlSchemaSet w obiekcie (pamięci podręcznej). Te scenariusze są opisane na stronie referencyjnej Create . XmlReader nie obsługuje weryfikacji schematu XML-Data Reduced (XDR).

W klasie są używane następujące ustawienia XmlReaderSettings , aby określić typ weryfikacji, jeśli istnieje, XmlReader wystąpienie obsługuje.

Użyj tego XmlReaderSettings elementu członkowskiego Aby określić
DtdProcessing Właściwość Czy zezwolić na przetwarzanie DTD. Wartością domyślną jest nie zezwalanie na przetwarzanie DTD.
ValidationType Właściwość Czy czytelnik powinien zweryfikować dane, oraz jakiego typu walidację należy wykonać (DTD lub schemat). Wartość domyślna to brak walidacji danych.
ValidationEventHandler Zdarzenie Procedura obsługi zdarzeń służąca do odbierania informacji o zdarzeniach weryfikacji. Jeśli program obsługi zdarzeń nie zostanie podany, XmlException zostanie zgłoszony pierwszy błąd weryfikacji.
ValidationFlags Właściwość Dodatkowe opcje walidacji za pośrednictwem elementów XmlSchemaValidationFlags członkowskich wyliczenia:

- AllowXmlAttributes-- Zezwalaj na atrybuty XML (xml:*) w dokumentach wystąpień nawet wtedy, gdy nie są zdefiniowane w schemacie. Atrybuty są weryfikowane na podstawie ich typu danych. Zobacz stronę referencyjną XmlSchemaValidationFlags ustawienia do użycia w określonych scenariuszach. (Domyślnie wyłączone).
- ProcessIdentityConstraints --Przetwarzanie ograniczeń tożsamości (xs:ID, xs:IDREF, xs:key, xs:keyref, xs:unique) napotkanych podczas walidacji. (Domyślnie włączone).
- ProcessSchemaLocation --Przetwarzanie schematów określonych przez xsi:schemaLocation atrybut or xsi:noNamespaceSchemaLocation . (Domyślnie włączone).
- ProcessInlineSchema-- Przetwarzanie wbudowanych schematów XML podczas walidacji. (Domyślnie wyłączone).
- ReportValidationWarnings--Zgłaszaj zdarzenia, jeśli wystąpi ostrzeżenie o walidacji. Ostrzeżenie jest zwykle wystawiane, gdy nie ma identyfikatora DTD lub schematu XML w celu zweryfikowania określonego elementu lub atrybutu. Element ValidationEventHandler jest używany do powiadamiania. (Domyślnie wyłączone).
Schemas Element XmlSchemaSet do użycia do weryfikacji.
XmlResolver Właściwość Element XmlResolver do rozpoznawania i uzyskiwania dostępu do zasobów zewnętrznych. Może to obejmować jednostki zewnętrzne, takie jak DTD i schematy, oraz wszystkie xs:include elementy lub xs:import zawarte w schemacie XML. Jeśli nie określisz XmlResolverwartości , XmlReader zostanie użyta wartość domyślna XmlUrlResolver bez poświadczeń użytkownika.

Zgodność danych

Czytniki XML tworzone przez metodę Create domyślnie spełniają następujące wymagania dotyczące zgodności:

  • Nowe wiersze i wartość atrybutu są znormalizowane zgodnie z zaleceniem W3C XML 1.0.

  • Wszystkie jednostki są automatycznie rozwinięte.

  • Atrybuty domyślne zadeklarowane w definicji typu dokumentu są zawsze dodawane nawet wtedy, gdy czytelnik nie sprawdza poprawności.

  • Deklaracja prefiksu XML zamapowanego na prawidłowy identyfikator URI przestrzeni nazw XML jest dozwolona.

  • Nazwy notacji w pojedynczej NotationType deklaracji atrybutu i NmTokens w jednej Enumeration deklaracji atrybutu są odrębne.

Użyj tych XmlReaderSettings właściwości, aby określić typ kontroli zgodności, które chcesz włączyć:

Użyj tej XmlReaderSettings właściwości To Wartość domyślna
CheckCharacters Właściwość Włącz lub wyłącz kontrole dla następujących elementów:

- Znaki znajdują się w zakresie znaków prawnych XML, zgodnie z definicją w sekcji 2.2 Znaki zalecenia W3C XML 1.0.
— Wszystkie nazwy XML są prawidłowe, zgodnie z definicją w sekcji Typowe konstrukcje składniowe 2.3 zalecenia W3C XML 1.0.

Gdy ta właściwość jest ustawiona na true (wartość domyślna), zgłaszany jest wyjątek, XmlException jeśli plik XML zawiera niedozwolone znaki lub nieprawidłowe nazwy XML (na przykład nazwa elementu zaczyna się od liczby).
Sprawdzanie znaków i nazw jest włączone.

Ustawienie CheckCharacters powoduje false wyłączenie sprawdzania znaków dla odwołań do jednostki znaków. Jeśli czytelnik przetwarza dane tekstowe, zawsze sprawdza, czy nazwy XML są prawidłowe, niezależnie od tego ustawienia. Uwaga: zalecenie XML 1.0 wymaga zgodności na poziomie dokumentu, gdy istnieje dtD. W związku z tym, jeśli czytnik jest skonfigurowany do obsługi ConformanceLevel.Fragment, ale dane XML zawierają definicję typu dokumentu (DTD), XmlException jest zgłaszany.
ConformanceLevel Właściwość Wybierz poziom zgodności, aby wymusić:

- Document. Jest zgodny z regułami dobrze sformułowanego dokumentu XML 1.0.
- Fragment. Jest zgodna z regułami fragmentu dobrze sformułowanego dokumentu, który może być używany jako zewnętrzna jednostka analizowana.
- Auto. Jest zgodny z poziomem określonym przez czytelnika.

Jeśli dane nie są zgodne, XmlException zgłaszany jest wyjątek.
Document

Bieżący węzeł to węzeł XML, w którym obecnie znajduje się czytnik XML. Wszystkie XmlReader metody wykonują operacje w odniesieniu do tego węzła, a wszystkie XmlReader właściwości odzwierciedlają wartość bieżącego węzła.

Poniższe metody ułatwiają nawigowanie po węzłach i analizowanie danych.

Użyj tej XmlReaderSettings metody To
Read Odczytywanie pierwszego węzła i przechodzenie przez strumień po jednym węźle jednocześnie. Takie wywołania są zwykle wykonywane wewnątrz while pętli.

NodeType Użyj właściwości , aby uzyskać typ (na przykład atrybut, komentarz, element itd.) bieżącego węzła.
Skip Pomiń elementy podrzędne bieżącego węzła i przejdź do następnego węzła.
MoveToContent i MoveToContentAsync Pomiń węzły inne niż zawartość i przejdź do następnego węzła zawartości lub na końcu pliku.

Węzły niezwiązane z zawartością obejmują ProcessingInstruction: , DocumentType, Comment, Whitespacei SignificantWhitespace.

Węzły zawartości zawierają tekst inny niż biały, CDATA, EntityReference i EndEntity.
ReadSubtree Odczytaj element i wszystkie jego elementy podrzędne i zwróć nowe XmlReader wystąpienie ustawione na ReadState.Initialwartość .

Ta metoda jest przydatna do tworzenia granic wokół elementów XML; Na przykład jeśli chcesz przekazać dane do innego składnika do przetwarzania i chcesz ograniczyć ilość danych, do których składnik może uzyskać dostęp.

XmlReader.Read Zobacz stronę referencyjną, aby zapoznać się z przykładem nawigowania po strumieniu tekstowym po jednym węźle i wyświetlania typu każdego węzła.

W poniższych sekcjach opisano sposób odczytywania określonych typów danych, takich jak elementy, atrybuty i typizowane dane.

Odczytywanie elementów XML

W poniższej tabeli wymieniono metody i właściwości, które XmlReader udostępnia klasa do przetwarzania elementów. XmlReader Po ustawieniu elementu właściwości węzła, takie jak Name, odzwierciedlają wartości elementu. Oprócz elementów członkowskich opisanych poniżej można również używać dowolnych ogólnych metod i właściwości XmlReader klasy do przetwarzania elementów. Na przykład możesz użyć ReadInnerXml metody , aby odczytać zawartość elementu.

Uwaga

Zobacz sekcję 3.1 zalecenia W3C XML 1.0, aby zapoznać się z definicjami tagów początkowych, tagów końcowych i pustych tagów elementów.

Użyj tego XmlReader elementu członkowskiego To
IsStartElement Metoda Sprawdź, czy bieżący węzeł jest tagiem początkowym lub pustym tagiem elementu.
ReadStartElement Metoda Sprawdź, czy bieżący węzeł jest elementem i przejdź do następnego węzła (wywołania IsStartElement , a następnie Read).
ReadEndElement Metoda Sprawdź, czy bieżący węzeł jest tagiem końcowym i przejdź do następnego węzła.
ReadElementString Metoda Odczytywanie elementu tylko do tekstu.
ReadToDescendant Metoda Przejdź do następnego elementu podrzędnego (podrzędnego), który ma określoną nazwę, przejdź do czytnika XML.
ReadToNextSibling Metoda Przejdź do następnego elementu równorzędnego czytnika XML, który ma określoną nazwę.
IsEmptyElement Właściwość Sprawdź, czy bieżący element ma tag elementu końcowego. Na przykład:

- <item num="123"/> (IsEmptyElement to true.)
- <item num="123"> </item> (IsEmptyElement to , falsechociaż zawartość elementu jest pusta).

Aby zapoznać się z przykładem odczytywania zawartości tekstowej elementów, zobacz metodę ReadString . Poniższy przykład przetwarza elementy przy użyciu while pętli.

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

Odczytywanie atrybutów XML

Atrybuty XML są najczęściej spotykane w elementach, ale są również dozwolone w węzłach deklaracji XML i typu dokumentu.

Po ustawieniu pozycji w węźle MoveToAttribute elementu metoda umożliwia przejście przez listę atrybutów elementu. Należy pamiętać, że po MoveToAttribute wywołaniu właściwości węzła, takie jak Name, NamespaceURIi Prefix odzwierciedlają właściwości tego atrybutu, a nie właściwości elementu, do którego należy atrybut.

Klasa XmlReader udostępnia te metody i właściwości do odczytywania i przetwarzania atrybutów elementów.

Użyj tego XmlReader elementu członkowskiego To
HasAttributes Właściwość Sprawdź, czy bieżący węzeł ma jakiekolwiek atrybuty.
AttributeCount Właściwość Pobierz liczbę atrybutów w bieżącym elemencie.
MoveToFirstAttribute Metoda Przejdź do pierwszego atrybutu w elemecie .
MoveToNextAttribute Metoda Przejdź do następnego atrybutu w elemecie .
MoveToAttribute Metoda Przejdź do określonego atrybutu.
GetAttribute metoda lub Item[] właściwość Pobierz wartość określonego atrybutu.
IsDefault Właściwość Sprawdź, czy bieżący węzeł jest atrybutem wygenerowanym na podstawie wartości domyślnej zdefiniowanej w dtD lub schemacie.
MoveToElement Metoda Przejdź do elementu, który jest właścicielem bieżącego atrybutu. Użyj tej metody, aby powrócić do elementu po przejściu przez jego atrybuty.
ReadAttributeValue Metoda Przeanalizuj wartość atrybutu w co najmniej jednym Textwęźle , EntityReferencelub EndEntity węzłach.

Dowolnego z ogólnych XmlReader metod i właściwości można również używać do przetwarzania atrybutów. Na przykład po ustawieniu atrybutu XmlReader właściwości Name i Value odzwierciedlają wartości atrybutu . Możesz również użyć dowolnej metody zawartości Read , aby uzyskać wartość atrybutu.

W tym przykładzie użyto AttributeCount właściwości do nawigowania po wszystkich atrybutach elementu.

// 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

W tym przykładzie while użyto MoveToNextAttribute metody w pętli w celu nawigowania po atrybutach.

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

Odczytywanie atrybutów w węzłach deklaracji XML

Gdy czytnik XML jest umieszczony w węźle deklaracji XML, Value właściwość zwraca informacje o wersji, autonomicznej i kodowaniu jako pojedynczy ciąg. XmlReader obiekty utworzone przez metodę Create , XmlTextReader klasę i XmlValidatingReader klasę uwidaczniają wersję, autonomiczną i kodowanie elementów jako atrybuty.

Odczytywanie atrybutów w węzłach typu dokumentu

Gdy czytnik XML jest umieszczony w węźle typu dokumentu, GetAttribute metoda i Item[] właściwość mogą służyć do zwracania wartości literałów SYSTEM i PUBLIC. Na przykład wywołanie reader.GetAttribute("PUBLIC") zwraca wartość PUBLIC.

Odczytywanie atrybutów przetwarzania węzłów instrukcji

Gdy właściwość XmlReader jest umieszczona w węźle instrukcji przetwarzania, Value właściwość zwraca całą zawartość tekstową. Elementy w węźle instrukcji przetwarzania nie są traktowane jako atrybuty. Nie można ich odczytać za pomocą GetAttribute metody lub MoveToAttribute .

Odczytywanie zawartości XML

Klasa XmlReader zawiera następujące elementy członkowskie, które odczytują zawartość z pliku XML i zwracają zawartość jako wartości ciągu. (Aby zwrócić typy CLR, zobacz Przekonwertuj na typy CLR).

Użyj tego XmlReader elementu członkowskiego To
Value Właściwość Pobierz zawartość tekstowa bieżącego węzła. Zwrócona wartość zależy od typu węzła; Aby uzyskać szczegółowe informacje, zobacz stronę referencyjną Value .
ReadString Metoda Pobierz zawartość elementu lub węzła tekstowego jako ciąg. Ta metoda zatrzymuje się na przetwarzaniu instrukcji i komentarzy.

Aby uzyskać szczegółowe informacje na temat sposobu obsługi określonych typów węzłów przez tę metodę, zobacz stronę referencyjną ReadString .
ReadInnerXml i ReadInnerXmlAsync metody Pobierz całą zawartość bieżącego węzła, w tym znaczniki, ale z wyłączeniem tagów początkowych i końcowych. Na przykład dla:

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

ReadInnerXml Zwraca:

this<child id="123"/>
ReadOuterXml i ReadOuterXmlAsync metody Pobierz całą zawartość bieżącego węzła i jego elementów podrzędnych, w tym znaczniki i tagi początkowe/końcowe. Na przykład dla:

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

ReadOuterXml Zwraca:

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

Konwertowanie na typy CLR

Elementy członkowskie XmlReader klasy (wymienione w poniższej tabeli) umożliwiają odczytywanie danych XML i zwracanie wartości jako typów środowiska uruchomieniowego języka wspólnego (CLR) zamiast ciągów. Te elementy członkowskie umożliwiają uzyskanie wartości w reprezentacji, która jest najbardziej odpowiednia dla zadania kodowania bez konieczności ręcznego analizowania lub konwertowania wartości ciągów.

  • Metody ReadElementContentAs można wywoływać tylko w typach węzłów elementów. Tych metod nie można używać w elementach zawierających elementy podrzędne lub mieszaną zawartość. Po wywołaniu XmlReader obiekt odczytuje tag startowy, odczytuje zawartość elementu, a następnie przechodzi obok tagu elementu końcowego. Instrukcje przetwarzania i komentarze są ignorowane, a jednostki są rozszerzane.

  • Metody ReadContentAs odczytują zawartość tekstowa na bieżącej pozycji czytnika, a jeśli dane XML nie mają skojarzonych z nim żadnych informacji o schemacie lub typie danych, przekonwertuj zawartość tekst na żądany typ zwracany. Tekst, biały znak, znaczące odstępy i sekcje CDATA są łączone. Komentarze i instrukcje przetwarzania są pomijane, a odwołania do jednostek są automatycznie rozwiązywane.

Klasa XmlReader używa reguł zdefiniowanych przez rekomendację Schemat XML W3C — część 2: Zalecenia dotyczące typów danych.

Użyj tej XmlReader metody Aby zwrócić ten typ CLR
ReadContentAsBoolean i ReadElementContentAsBoolean Boolean
ReadContentAsDateTime i ReadElementContentAsDateTime DateTime
ReadContentAsDouble i ReadElementContentAsDouble Double
ReadContentAsLong i ReadElementContentAsLong Int64
ReadContentAsInt i ReadElementContentAsInt Int32
ReadContentAsString i ReadElementContentAsString String
ReadContentAs i ReadElementContentAs Typ określony za pomocą parametru returnType
ReadContentAsObject i ReadElementContentAsObject Najbardziej odpowiedni typ, określony przez XmlReader.ValueType właściwość . Aby uzyskać informacje o mapowaniu, zobacz Obsługa typów w klasach System.Xml.

Jeśli nie można łatwo przekonwertować elementu na typ CLR ze względu na jego format, możesz użyć mapowania schematu, aby zapewnić pomyślną konwersję. W poniższym przykładzie użyto pliku xsd do przekonwertowania hire-date elementu na xs:date typ, a następnie użyto ReadElementContentAsDateTime metody , aby zwrócić element jako DateTime obiekt.

Dane wejściowe (hireDate.xml):

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

Schemat (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>

Kod:

// 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

Wyjście:

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

Programowanie asynchroniczne

XmlReader Większość metod ma asynchroniczne odpowiedniki, które mają wartość "Async" na końcu nazw metod. Na przykład asynchroniczny odpowiednik elementu ReadContentAsObject to ReadContentAsObjectAsync.

Następujące metody mogą być używane z wywołaniami metody asynchronicznej:

W poniższych sekcjach opisano asynchroniczne użycie metod, które nie mają asynchronicznych odpowiedników.

ReadStartElement, metoda

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, metoda

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, metoda

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, metoda

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, metoda

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

Zagadnienia dotyczące zabezpieczeń

Podczas pracy z klasą XmlReader należy wziąć pod uwagę następujące kwestie:

  • Wyjątki zgłaszane przez program XmlReader mogą ujawniać informacje o ścieżkach, których możesz nie chcieć umieścić w aplikacji. Aplikacja musi przechwytywać wyjątki i odpowiednio je przetwarzać.

  • Nie włączaj przetwarzania DTD, jeśli martwisz się o problemy z odmową usługi lub jeśli masz do czynienia z niezaufanymi źródłami. Przetwarzanie DTD jest domyślnie wyłączone dla XmlReader obiektów utworzonych przez metodę Create .

    Jeśli masz włączone przetwarzanie DTD, możesz użyć polecenia XmlSecureResolver , aby ograniczyć zasoby, do których XmlReader można uzyskać dostęp. Możesz również zaprojektować aplikację, aby przetwarzanie XML było ograniczone pamięci i czasu. Możesz na przykład skonfigurować limity czasu w aplikacji ASP.NET.

  • Dane XML mogą zawierać odwołania do zasobów zewnętrznych, takich jak plik schematu. Domyślnie zasoby zewnętrzne są rozwiązywane przy użyciu XmlUrlResolver obiektu bez poświadczeń użytkownika. Możesz to dodatkowo zabezpieczyć, wykonując jedną z następujących czynności:

  • Flagi ProcessInlineSchemaXmlReaderSettings i ProcessSchemaLocation walidacji obiektu nie są domyślnie ustawione. Pomaga to chronić XmlReader przed atakami opartymi na schemacie podczas przetwarzania danych XML z niezaufanego źródła. Gdy te flagi są ustawione, XmlResolverXmlReaderSettings obiekt jest używany do rozpoznawania lokalizacji schematu napotkanych w dokumencie wystąpienia w XmlReaderpliku . XmlResolver Jeśli właściwość jest ustawiona na null, lokalizacje schematu nie są rozpoznawane, nawet jeśli ProcessInlineSchema flagi i ProcessSchemaLocation walidacji są ustawione.

    Schematy dodane podczas walidacji dodają nowe typy i mogą zmienić wynik weryfikacji weryfikowanego dokumentu. W związku z tym schematy zewnętrzne powinny być rozpoznawane tylko z zaufanych źródeł.

    Zalecamy wyłączenie flagi ProcessIdentityConstraints podczas weryfikowania niezaufanych, dużych dokumentów XML w scenariuszach wysokiej dostępności względem schematu, który ma ograniczenia tożsamości w dużej części dokumentu. Ta flaga jest domyślnie włączona.

  • Dane XML mogą zawierać dużą liczbę atrybutów, deklaracji przestrzeni nazw, zagnieżdżonych elementów itd., które wymagają znacznego czasu na przetworzenie. Aby ograniczyć rozmiar danych wejściowych wysyłanych do XmlReaderelementu , możesz:

  • Metoda ReadValueChunk może służyć do obsługi dużych strumieni danych. Ta metoda odczytuje niewielką liczbę znaków jednocześnie zamiast przydzielać jeden ciąg dla całej wartości.

  • Podczas odczytywania dokumentu XML z dużą liczbą unikatowych nazw lokalnych, przestrzeni nazw lub prefiksów może wystąpić problem. Jeśli używasz klasy, która pochodzi z XmlReaderklasy , i wywołujesz LocalNamewłaściwość , Prefixlub NamespaceURI dla każdego elementu, zwracany ciąg zostanie dodany do NameTableelementu . Kolekcja przechowywana przez element nigdy nie zmniejsza rozmiaru NameTable , tworząc wirtualny wyciek pamięci uchwytów ciągów. Jednym z środków zaradczych jest wyprowadzenie z NameTable klasy i wymuszenie maksymalnego limitu przydziału rozmiaru. (Nie ma możliwości zapobiegania używaniu NameTableobiektu lub przełączania NameTable , gdy jest pełny). Innym ograniczeniem jest unikanie używania wymienionych właściwości, a zamiast tego należy użyć MoveToAttribute metody z IsStartElement metodą tam, gdzie to możliwe. Metody te nie zwracają ciągów, a tym samym uniknąć problemu nadmiernego NameTable wypełniania kolekcji.

  • XmlReaderSettings obiekty mogą zawierać poufne informacje, takie jak poświadczenia użytkownika. Niezaufany składnik może używać XmlReaderSettings obiektu i jego poświadczeń użytkownika do tworzenia XmlReader obiektów do odczytywania danych. Podczas buforowania XmlReaderSettings obiektów lub przekazywania XmlReaderSettings obiektu z jednego składnika do innego należy zachować ostrożność.

  • Nie akceptuj składników pomocniczych, takich jak NameTable, XmlNamespaceManageri , XmlResolver z niezaufanego źródła.