System.Xml.XmlReader-Klasse

Dieser Artikel enthält ergänzende Hinweise zur Referenzdokumentation für diese API.

XmlReader ermöglicht schreibgeschützten Forward-Only-Zugriff auf XML-Daten in einem Dokument oder Stream. Diese Klasse entspricht den W3C-Empfehlungen der vierte Edition von Extensible Markup Language 1.0 (XML) und dritten Edition von Namespaces in XML 1.0.

Mit XmlReader-Methoden können Sie XML-Daten durchlaufen und den Inhalt eines Knotens lesen. Die Eigenschaften der Klasse spiegeln den Wert des aktuellen Knotens wider, an dem der Reader positioniert ist. Der Wert der ReadState-Eigenschaft gibt den aktuellen Status des XML-Readers an. Die Eigenschaft wird z. B. von der XmlReader.Read-Methode auf ReadState.Initial festgelegt und von der XmlReader.Close-Methode auf ReadState.Closed. XmlReader stellt außerdem Datenkonformitätsprüfungen und -validierungen für eine DTD-Datei oder ein Schema bereit.

XmlReader verwendet ein Pullmodell zum Abrufen von Daten. Dieses Modell:

  • Vereinfacht die Statusverwaltung durch eine natürliche Prozedur von oben nach unten
  • Unterstützt mehrere Eingabestreams und ein Schichtenmodell
  • Ermöglicht es dem Client, dem Parser einen Puffer zu geben, in den die Zeichenfolge direkt geschrieben wird, und somit die Notwendigkeit einer zusätzlichen Zeichenfolgenkopie zu vermeiden
  • Unterstützt selektive Verarbeitung. Der Client kann Elemente überspringen und diejenigen verarbeiten, die für die Anwendung relevant sind. Sie können Eigenschaften auch im Voraus festlegen, um zu verwalten, wie der XML-Stream verarbeitet wird (z. B. Normalisierung).

Erstellen eines XML-Readers

Verwenden Sie die Create-Methode, um eine XmlReader-Instanz zu erstellen.

Obwohl .NET konkrete Implementierungen der XmlReader-Klasse bereitstellt, z. B. die XmlTextReader-, XmlNodeReader- und XmlValidatingReader-Klassen, wird empfohlen, die speziellen Klassen nur in diesen Szenarios zu verwenden:

  • Wenn Sie eine XML-DOM-Unterstruktur aus einem XmlNode-Objekt lesen möchten, verwenden Sie die XmlNodeReader-Klasse. (Diese Klasse unterstützt jedoch keine DTD- oder Schemavalidierung.)
  • Wenn Sie Entitäten auf Anforderung erweitern müssen und der Textinhalt nicht normalisiert und keine Standardattribute zurückgegeben werden sollen, verwenden Sie die XmlTextReader-Klasse.

Um die Features anzugeben, die Sie für den XML-Reader aktivieren möchten, übergeben Sie ein System.Xml.XmlReaderSettings-Objekt an die Create-Methode. Sie können ein einzelnes System.Xml.XmlReaderSettings-Objekt verwenden, um mehrere Reader mit derselben Funktionalität zu erstellen, oder das System.Xml.XmlReaderSettings-Objekt ändern, um einen neuen Reader mit anderen Features zu erstellen. Sie können auch problemlos Features zu einem vorhandenen Reader hinzufügen.

Wenn Sie kein System.Xml.XmlReaderSettings-Objekt verwenden, werden Standardeinstellungen verwendet. Weitere Informationen finden Sie auf der Create-Referenzseite.

XmlReader löst XmlException bei XML-Analysefehlern aus. Nach dem Auslösen einer Ausnahme ist der Status des Readers nicht vorhersehbar. Der gemeldete Knotentyp kann z. B. vom tatsächlichen Knotentyp des aktuellen Knotens abweichen. Verwenden Sie die ReadState-Eigenschaft, um zu überprüfen, ob sich der Reader in einem fehlerhaften Zustand befindet.

Validieren von XML-Daten

Um die Struktur eines XML-Dokuments und dessen Elementbeziehungen, Datentypen und Inhaltseinschränkungen anzugeben, verwenden Sie eine DTD (Document Type Definition) oder ein XSD-Schema (XML Schema Definition Language). Ein XML-Dokument gilt als wohlgeformt, wenn es alle syntaktischen Anforderungen erfüllt, die durch die W3C XML 1.0-Empfehlung definiert sind. Er gilt als gültig, wenn es wohlgeformt ist und den Einschränkungen entspricht, die durch seine DTD oder sein Schema definiert sind. (Weitere Informationen finden Sie in den Empfehlungen W3C XML Schema Part 1: Structures und W3C XML Schema Part 2: Datatypes.) Das heißt, dass alle gültigen XML-Dokumente wohlgeformt sind, jedoch nicht alle wohlgeformten XML-Dokumente gültig sein müssen.

Sie können die Daten anhand einer DTD, eines XSD-Inlineschemas oder eines XSD-Schemas validieren, das in einem XmlSchemaSet-Objekt (einem Cache) gespeichert ist. Diese Szenarios werden auf der Create-Referenzseite beschrieben. XmlReader unterstützt keine XDR-Schemavalidierung (XML-Data Reduced).

Sie verwenden die folgenden Einstellungen für die XmlReaderSettings-Klasse, um anzugeben, welche Art von Validierung, falls überhaupt, die XmlReader-Instanz unterstützt.

Diesen XmlReaderSettings-Member verwenden Angabe von
DtdProcessing-Eigenschaft Gibt an, ob eine DTD-Verarbeitung zulässig ist. In der Standardeinstellung ist die DTD-Verarbeitung nicht zulässig.
ValidationType-Eigenschaft Gibt an, ob der Reader Daten validieren und welche Art von Validierung erfolgen soll (DTD oder Schema). In der Standardeinstellung erfolgt keine Validierung.
ValidationEventHandler -Ereignis Gibt einen Ereignishandler an, mit dem Informationen über Validierungsereignisse empfangen werden. Wenn kein Ereignishandler bereitgestellt wird, wird beim ersten Validierungsfehler eine XmlException ausgelöst.
ValidationFlags-Eigenschaft Gibt zusätzliche Validierungsoptionen über die XmlSchemaValidationFlags-Enumerationsmember an:

- AllowXmlAttributes: XML-Attribute (xml:*) in Instanzdokumenten auch dann zulassen, wenn sie nicht im Schema definiert sind. Die Attribute werden anhand ihres Datentyps validiert. Die Einstellung, die in bestimmten Szenarios verwendet werden soll, finden Sie auf der XmlSchemaValidationFlags-Referenzseite. (standardmäßig deaktiviert)
- ProcessIdentityConstraints: Während der Validierung auftretende Identitätseinschränkungen (xs:ID, xs:IDREF, xs:key, xs:keyref, xs:unique) verarbeiten (standardmäßig aktiviert)
- ProcessSchemaLocation: Schemas verarbeiten, die durch das xsi:schemaLocation- oder xsi:noNamespaceSchemaLocation-Attribut angegeben werden (standardmäßig aktiviert)
- ProcessInlineSchema: XML-Inlineschemas während der Validierung verarbeiten (standardmäßig deaktiviert)
- ReportValidationWarnings: Ereignisse melden, wenn eine Validierungswarnung auftritt Eine Warnung wird normalerweise ausgegeben, wenn keine DTD oder kein XML-Schema vorhanden ist, anhand derer bzw. dessen ein bestimmtes Attribut oder Element validiert werden kann. ValidationEventHandler wird zur Benachrichtigung verwendet. (standardmäßig deaktiviert)
Schemas Die für die Validierung zu verwendende XmlSchemaSet.
XmlResolver-Eigenschaft XmlResolver wird zum Auflösen von und Zugreifen auf externe Ressourcen verwendet. Dazu können externe Entitäten wie DTD-Dateien und Schemas sowie alle im XML-Schema enthaltenen xs:include- oder xs:import-Elemente zählen. Wenn Sie XmlResolver nicht angeben, verwendet XmlReader einen Standardwert ohne Benutzeranmeldeinformationen für XmlUrlResolver.

Datenkonformität

XML-Reader, die von der Create-Methode erstellt werden, erfüllen standardmäßig die folgenden Complianceanforderungen:

  • Neue Zeilen und Attributwerte werden gemäß der W3C-Empfehlung für XML 1.0 normalisiert.

  • Alle Entitäten werden automatisch erweitert.

  • In der Dokumenttypdefinition deklarierte Standardattribute werden immer hinzugefügt, auch wenn der Reader diese nicht validiert.

  • Die Deklaration eines XML-Präfixes, das dem richtigen XML-Namespace-URI zugeordnet ist, ist zulässig.

  • Die Notationsnamen in einer einzelnen NotationType-Attributdeklaration und NmTokens in einer einzelnen Enumeration-Attributdeklaration unterscheiden sich.

Verwenden Sie diese XmlReaderSettings-Eigenschaften, um anzugeben, welche Konformitätsprüfungen Sie aktivieren möchten:

Diese XmlReaderSettings-Eigenschaft verwenden Beschreibung Standard
CheckCharacters-Eigenschaft Aktivieren oder deaktivieren Sie Überprüfungen für Folgendes:

– Zeichen befinden sich innerhalb des Gültigkeitsbereichs für XML-Zeichen, der im Abschnitt 2.2 Characters der W3C-Empfehlung für XML 1.0 definiert ist.
– Alle XML-Namen sind gültig gemäß den Angaben im Abschnitt 2.3 Common Syntactic Constructs der W3C-Empfehlung für XML 1.0.

Wenn diese Eigenschaft auf true (Standardwert) festgelegt ist, wird eine XmlException-Ausnahme ausgelöst, wenn die XML-Datei ungültige Zeichen oder ungültige XML-Namen enthält (z. B. ein mit einer Zahl beginnender Elementname).
Die Zeichen- und Namensüberprüfung ist aktiviert.

Durch Festlegen von CheckCharacters auf false wird die Zeichenüberprüfung für Zeichenentitätsverweise deaktiviert. Wenn der Reader Textdaten verarbeitet, überprüft er immer, ob XML-Namen gültig sind, unabhängig von dieser Einstellung. Hinweis: Gemäß der Empfehlung für XML 1.0 muss bei vorhandener DTD eine Übereinstimmung auf Dokumentebene vorliegen. Wenn der Reader für die Unterstützung von ConformanceLevel.Fragment konfiguriert ist, die XML-Daten jedoch eine DTD (Document Type Definition) enthalten, wird daher XmlException ausgelöst.
ConformanceLevel-Eigenschaft Wählen Sie den Konformitätsgrad aus, die erzwungen werden soll:

- Document. Entspricht den Regeln für ein wohlgeformtes XML 1.0-Dokument
- Fragment. Entspricht den Regeln für ein wohlgeformtes Dokumentfragment, das als extern geparste Entität verwendet werden kann
- Auto. Entspricht dem vom Reader bestimmten Konformitätsgrad

Wenn die Daten nicht konform sind, wird eine XmlException-Ausnahme ausgelöst.
Document

Der aktuelle Knoten ist der XML-Knoten, auf dem sich der XML-Reader gerade befindet. Alle XmlReader-Methoden führen Vorgänge in Bezug auf diesen Knoten aus, und alle XmlReader-Eigenschaften spiegeln den Wert des aktuellen Knotens wider.

Mit den folgenden Methoden können Sie einfach durch Knoten navigieren und Daten analysieren.

Diese XmlReaderSettings-Methode verwenden Beschreibung
Read Lesen Sie den ersten Knoten, und durchlaufen Sie den Stream Knoten für Knoten. Solche Aufrufe werden normalerweise in einer while-Schleife ausgeführt.

Verwenden Sie die NodeType-Eigenschaft, um den Typ (z. B. Attribut, Kommentar, Element) des aktuellen Knotens abzurufen.
Skip Überspringen Sie die untergeordneten Elemente des aktuellen Knotens, und fahren Sie mit dem nächsten Knoten fort.
MoveToContent und MoveToContentAsync Überspringen Sie Nicht-Inhaltsknoten, und fahren Sie mit dem nächsten Inhaltsknoten fort, oder springen Sie zum Ende der Datei.

Zu Nicht-Inhaltsknoten zählen ProcessingInstruction, DocumentType, Comment, Whitespace und SignificantWhitespace.

Zu Inhaltsknoten zählen Textknoten ohne Leerzeichen wie CDATA, EntityReference und EndEntity.
ReadSubtree Lesen Sie ein Element und alle untergeordneten Elemente, und geben Sie eine neue XmlReader-Instanz zurück, die auf ReadState.Initial festgelegt ist.

Diese Methode ist nützlich, um Grenzen für XML-Elemente zu erstellen: Wenn Sie z. B. Daten zur Verarbeitung an eine andere Komponente übergeben und einschränken möchten, auf wie viele Daten die Komponente zugreifen kann.

Auf der XmlReader.Read-Referenzseite finden Sie ein Beispiel für die knotenweise Navigation durch einen Textstream und zum Anzeigen des Typs der einzelnen Knoten.

In den folgenden Abschnitten wird beschrieben, wie Sie bestimmte Datentypen lesen können, z. B. Elemente, Attribute und typisierte Daten.

Lesen von XML-Elementen

In der folgenden Tabelle werden die Methoden und Eigenschaften aufgeführt, die die XmlReader-Klasse für Verarbeitungselemente bereitstellt. Nachdem der XmlReader auf einem Element platziert wurde, spiegeln die Knoteneigenschaften, z. B. Name, die Elementwerte wider. Zusätzlich zu den unten beschriebenen Membern können auch alle allgemeinen Methoden und Eigenschaften der XmlReader-Klasse zum Verarbeiten von Elementen verwendet werden. Sie können beispielsweise mit der ReadInnerXml-Methode den Inhalt eines Elements lesen.

Hinweis

Im Abschnitt 3.1 der W3C-Empfehlung für XML 1.0 finden Sie Definitionen für Starttags, Endtags und leere Elementtags.

Diesen XmlReader-Member verwenden Beschreibung
IsStartElement-Methode Überprüft, ob der aktuelle Knoten ein Anfangstag oder ein leeres Elementtag ist
ReadStartElement-Methode Überprüft, ob es sich bei dem aktuellen Knoten um ein Element handelt, und fährt mit dem nächsten Knoten fort (ruft IsStartElement gefolgt von Read auf)
ReadEndElement-Methode Überprüft, ob der aktuelle Knoten ein Endtag ist, und rückt den Reader zum nächsten Knoten vor
ReadElementString-Methode Liest ein Nur-Text-Element
ReadToDescendant-Methode Rückt den XML-Reader zum nächsten untergeordneten Element mit dem angegebenen Namen vor
ReadToNextSibling-Methode Rückt den XML-Reader zum nächsten gleichgeordneten Element mit dem angegebenen Namen vor
IsEmptyElement-Eigenschaft Überprüft, ob das aktuelle Element ein Endelementtag aufweist Beispiel:

- <item num="123"/> (IsEmptyElement ist true)
- <item num="123"> </item> (IsEmptyElement ist false, obwohl der Inhalt des Elements leer ist.)

Ein Beispiel zum Lesen des Textinhalts von Elementen finden Sie in der ReadString-Methode. Im folgenden Beispiel werden Elemente mithilfe einer while-Schleife verarbeitet.

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

Lesen von XML-Attributen

XML-Attribute werden am häufigsten für Elemente verwendet, sind aber auch für XML-Deklarations- und Dokumenttypknoten zulässig.

Bei Positionierung in einem Elementknoten ermöglicht die MoveToAttribute-Methode das Durchlaufen der Attributliste des Elements. Beachten Sie, dass nach dem Aufruf von MoveToAttribute Knoteneigenschaften wie Name, NamespaceURI und Prefix die Eigenschaften dieses Attributs widerspiegeln, nicht die Eigenschaften des Elements, zu dem das Attribut gehört.

Die XmlReader-Klasse stellt diese Methoden und Eigenschaften zum Lesen und Verarbeiten von Attributen für Elemente bereit.

Diesen XmlReader-Member verwenden Beschreibung
HasAttributes-Eigenschaft Überprüft, ob der aktuelle Knoten Attribute aufweist
AttributeCount-Eigenschaft Ruft die Anzahl der Attribute im aktuellen Element ab
MoveToFirstAttribute-Methode Wechselt zum ersten Attribut in einem Element
MoveToNextAttribute-Methode Wechselt zum nächsten Attribut in einem Element
MoveToAttribute-Methode Wechselt zu einem angegebenen Attribut
GetAttribute-Methode oder Item[]-Eigenschaft Ruft den Wert eines angegebenen Attributs ab
IsDefault-Eigenschaft Überprüft, ob der aktuelle Knoten ein Attribut ist, das aus dem in der DTD oder dem Schema definierten Standardwert generiert wurde
MoveToElement-Methode Wechselt zum Element, das das aktuelle Attribut besitzt. Verwenden Sie diese Methode, um nach dem Navigieren durch die Attribute zu einem Element zurückzukehren.
ReadAttributeValue-Methode Parst den Attributwert in einen oder mehrere Text-, EntityReference- oder EndEntity-Knoten.

Alle allgemeinen Methoden und Eigenschaften von XmlReader können auch für die Verarbeitung von Attributen verwendet werden. Beispielsweise reflektieren die XmlReader-Eigenschaft und die Name-Eigenschaft nach dem Positionieren von Value auf einem Attribut die Werte des Attributs. Sie können den Wert des Attributs auch mit einer beliebigen Read-Methode für den Inhalt abrufen.

In diesem Beispiel wird die AttributeCount-Eigenschaft verwendet, um durch alle Attribute eines Elements zu navigieren.

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

In diesem Beispiel wird die MoveToNextAttribute-Methode in einer while-Schleife verwendet, um durch die Attribute zu navigieren.

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

Lesen von Attributen in XML-Deklarationsknoten

Wenn der XML-Reader auf einem XML-Deklarationsknoten positioniert ist, gibt die Value-Eigenschaft die Informationen zu Version, Eigenständigkeit und Codierung von als einzelne Zeichenfolge zurück. XmlReader-Objekte, die von der Create-Methode, der XmlTextReader-Klasse und der XmlValidatingReader Klasse erstellt wurden, machen die Elemente für Version, Eigenständigkeit und Codierung als Attribute verfügbar.

Lesen von Attributen in Dokumenttypknoten

Wenn der XML-Reader in einem Dokumenttypknoten positioniert ist, können die Werte für die Literale SYSTEM und PUBLIC mithilfe der GetAttribute-Methode und der Item[]-Eigenschaft zurückgegeben werden. Durch das Aufrufen von reader.GetAttribute("PUBLIC") wird beispielsweise der Wert PUBLIC zurückgegeben.

Lesen von Attributen für die Verarbeitung von Anweisungsknoten

Wenn der XmlReader auf einem Verarbeitungsanweisungsknoten positioniert ist, gibt die Value-Eigenschaft den gesamten Textinhalt zurück. Elemente im Verarbeitungsanweisungsknoten werden nicht als Attribute behandelt. Sie können nicht mit der GetAttribute- oder MoveToAttribute-Methode gelesen werden.

Lesen von XML-Inhalt

Die XmlReader-Klasse enthält die folgenden Member, die Inhalte aus einer XML-Datei lesen und den Inhalt als Zeichenfolgenwerte zurückgeben. (Informationen zum Zurückgeben von CLR-Typen finden Sie unter Konvertieren in CLR-Typen.)

Diesen XmlReader-Member verwenden Beschreibung
Value-Eigenschaft Rufen Sie den Textinhalt des aktuellen Knotens ab. Der zurückgegebene Wert hängt vom Knotentyp ab. Weitere Informationen finden Sie auf der Value-Referenzseite.
ReadString-Methode Ruft den Inhalt eines Element- oder Textknotens als Zeichenfolge ab. Diese Methode wird bei Verarbeitungsanweisungen und Kommentaren angehalten.

Ausführliche Informationen zur Verarbeitung bestimmter Knotentypen durch diese Methode finden Sie auf der ReadString-Referenzseite.
Die Methoden ReadInnerXml und ReadInnerXmlAsync Ruft den gesamten Inhalt des aktuellen Knotens ab, einschließlich Markup, mit Ausnahme von Start- und Endtags. Beispiel:

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

ReadInnerXml gibt Folgendes zurück:

this<child id="123"/>
Die Methoden ReadOuterXml und ReadOuterXmlAsync Ruft alle Inhalte des aktuellen Knotens und der untergeordneten Elemente ab, einschließlich Markup und Start-/Endtags. Beispiel:

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

ReadOuterXml gibt Folgendes zurück:

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

Konvertieren in CLR-Typen

Sie können die Member der XmlReader-Klasse (in der folgenden Tabelle aufgeführt) verwenden, um XML-Daten zu lesen und Werte als CLR-Typen (Common Language Runtime) anstatt als Zeichenfolgen zurückzugeben. Mit diesen Membern können Sie Werte in der Darstellung abrufen, die für Ihre Codierungsaufgabe am besten geeignet sind, ohne Zeichenfolgenwerte manuell parsen oder konvertieren zu müssen.

  • Die ReadElementContentAs-Methoden können nur in Elementknotentypen aufgerufen werden. Diese Methoden können nur für Elemente verwendet werden, die untergeordnete Elemente oder gemischten Inhalt enthalten. Bei einem Aufruf liest das XmlReader-Objekt das Anfangstag und den Elementinhalt und wird hinter das Endelementtag verschoben. Verarbeitungsanweisungen und Kommentare werden ignoriert und Entitäten erweitert.

  • Die ReadContentAs-Methoden lesen den Textinhalt an der aktuellen Leseposition, und wenn den XML-Daten keine Schema- oder Datentypinformationen zugeordnet sind, konvertieren Sie den Textinhalt in den angeforderten Rückgabetyp. Text, Leerraum, signifikanter Leerraum und CDATA-Abschnitte sind verkettet. Kommentare und Verarbeitungsanweisungen werden übersprungen und Entitätsverweise automatisch aufgelöst.

Die XmlReader-Klasse befolgt die in der W3C-Empfehlung XML Schema Part 2: Datatypes definierten Regeln.

Diese XmlReader-Methode verwenden CLR-Rückgabetyp
ReadContentAsBoolean und ReadElementContentAsBoolean Boolean
ReadContentAsDateTime und ReadElementContentAsDateTime DateTime
ReadContentAsDouble und ReadElementContentAsDouble Double
ReadContentAsLong und ReadElementContentAsLong Int64
ReadContentAsInt und ReadElementContentAsInt Int32
ReadContentAsString und ReadElementContentAsString String
ReadContentAs und ReadElementContentAs Der Typ, den Sie mit dem Parameter returnType angeben
ReadContentAsObject und ReadElementContentAsObject Der am besten geeignete Typ, wie durch die XmlReader.ValueType-Eigenschaft angegeben. Informationen zur Zuordnung finden Sie unter Typunterstützung in System.Xml-Klassen.

Wenn ein Element aufgrund seines Formats nicht einfach in einen CLR-Typ konvertiert werden kann, können Sie eine Schemazuordnung verwenden, um eine erfolgreiche Konvertierung sicherzustellen. Im folgenden Beispiel wird eine XSD-Datei verwendet, um das hire-date-Element in den xs:date-Typ zu konvertieren. Anschließend wird die ReadElementContentAsDateTime-Methode verwendet, um das Element als DateTime-Objekt zurückzugeben.

Eingabe (hireDate.xml):

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

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

Code:

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

Ausgabe:

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

Asynchrone Programmierung

Die meisten XmlReader-Methoden haben asynchrone Entsprechungen, die am Ende ihrer Methodennamen „Async“ aufweisen. Beispielsweise ist ReadContentAsObjectAsync das asynchrone Äquivalent von ReadContentAsObject.

Die folgenden Methoden können mit asynchronen Methodenaufrufen verwendet werden:

In den folgenden Abschnitten wird die asynchrone Verwendung für Methoden beschrieben, die nicht über asynchrone Entsprechungen verfügen.

ReadStartElement-Methode

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

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

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

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

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

Sicherheitshinweise

Beachten Sie beim Arbeiten mit der XmlReader-Klasse Folgendes:

  • Ausnahmen, die über XmlReader ausgelöst werden, können Pfadinformationen offenlegen, die nicht an die App weitergegeben werden sollen. Ihre App muss Ausnahmen erfassen und entsprechend verarbeiten.

  • Aktivieren Sie die DTD-Verarbeitung nicht, wenn Sie DoS-Probleme befürchten oder nicht vertrauenswürdigen Quellen arbeiten. Die DTD-Verarbeitung ist für XmlReader-Objekte, die von der Create-Methode erstellt wurden, standardmäßig deaktiviert.

    Wenn die DTD-Verarbeitung aktiviert ist, können die Ressourcen, auf die der XmlSecureResolver Zugriff hat, mit dem XmlReader eingeschränkt werden. Sie können die App auch so entwerfen, dass die XML-Verarbeitung bezüglich Arbeitsspeicher und Zeit eingeschränkt wird. In einer ASP.NET-App können beispielsweise Timeouts konfiguriert werden.

  • XML-Daten können Verweise auf externe Ressourcen (z. B. eine Schemadatei) enthalten. Standardmäßig werden externe Ressourcen mithilfe eines XmlUrlResolver-Objekts ohne Benutzeranmeldeinformationen aufgelöst. Durch die folgenden Aktionen können Sie die Sicherheit weiter erhöhen:

  • Die ProcessInlineSchema- und ProcessSchemaLocation-Validierungsflags eines XmlReaderSettings-Objekts werden nicht standardmäßig festgelegt. Dadurch wird der XmlReader bei der Verbarbeitung von XML-Daten aus einer nicht vertrauenswürdigen Quelle vor schemabasierten Angriffen geschützt. Wenn diese Flags festgelegt sind, wird der XmlResolver des XmlReaderSettings-Objekts verwendet, um die im Instanzdokument des XmlReader erkannten Schemaspeicherorte aufzulösen. Wenn die XmlResolver-Eigenschaft auf null festgelegt wird, werden die Schemaspeicherorte nicht aufgelöst, auch wenn die ProcessInlineSchema- und ProcessSchemaLocation-Validierungsflags festgelegt sind.

    Durch während der Validierung hinzugefügte Schemas werden neue Typen hinzugefügt, sodass das Validierungsergebnis des überprüften Dokuments möglicherweise geändert wird. Daher sollten externe Schemata nur von vertrauenswürdigen Quellen aufgelöst werden.

    Es wird empfohlen, das ProcessIdentityConstraints-Flag zu deaktivieren, wenn Sie nicht vertrauenswürdige, große XML-Dokumente in Szenarios mit Hochverfügbarkeit anhand eines Schemas validieren, das innerhalb des Dokuments einen großen Teil von Identitätseinschränkungen aufweist. Dieses Flag ist standardmäßig aktiviert.

  • XML-Daten können eine Vielzahl von Attributen, Namespacedeklarationen, geschachtelten Elementen usw. enthalten, deren Verarbeitung sehr zeitaufwendig ist. Um die Größe der an XmlReader gesendeten Eingabe einzuschränken, können Sie:

    • Die Größe des Dokuments beschränken, indem Sie die Eigenschaft MaxCharactersInDocument festlegen

    • Die Anzahl der Zeichen beschränken, die sich durch das Erweitern von Entitäten ergeben, indem Sie die MaxCharactersFromEntities-Eigenschaft einrichten

    • Eine benutzerdefinierte IStream-Implementierung für die XmlReader erstellen

  • Die ReadValueChunk-Methode kann verwendet werden, um große Streams zu verarbeiten. Mit dieser Methode wird jeweils eine kleine Anzahl von Zeichen gelesen, anstatt dem ganzen Wert eine einzelne Zeichenfolge zuzuweisen.

  • Beim Lesen eines XML-Dokuments mit einer großen Anzahl eindeutiger lokaler Namen, Namespaces oder Präfixe kann ein Problem auftreten. Wenn Sie eine von XmlReader abgeleitete Klasse verwenden und für jedes Element die Eigenschaft LocalName, Prefix oder NamespaceURI aufrufen, wird die zurückgegebene Zeichenfolge zu NameTable hinzugefügt. Die Größe der in der NameTable gespeicherten Collection nimmt nie ab, sodass ein virtueller Arbeitsspeicherverlust der Zeichenfolgenhandles eintritt. Eine Gegenmaßnahme hierfür besteht darin, von der NameTable-Klasse abzuleiten und ein maximales Größenkontingent zu erzwingen. (Es gibt keine Möglichkeit, die Verwendung von NameTable zu verhindern oder die NameTable-Klasse zu wechseln, wenn sie voll ist). Eine weitere Gegenmaßnahme besteht darin, die erwähnten Eigenschaften zu vermeiden und stattdessen die MoveToAttribute-Methode mit der IsStartElement-Methode zu verwenden, sofern möglich. Diese Methoden geben keine Zeichenfolgen zurück und vermeiden daher das Problem, die NameTable-Collection zu überfüllen.

  • XmlReaderSettings-Objekte können vertrauliche Informationen (z. B. Anmeldeinformationen des Benutzers) enthalten. Eine nicht vertrauenswürdige Komponente könnte mithilfe des XmlReaderSettings-Objekts und den Anmeldeinformationen des Benutzers XmlReader-Objekte erstellen, mit denen Daten gelesen werden können. Sie sollten beim Zwischenspeichern von XmlReaderSettings-Objekten oder bei der Übergabe eines XmlReaderSettings-Objekts von einer Komponente an eine andere sorgfältig vorgehen.

  • Achten Sie darauf, keine Unterstützung für Komponenten aus einer nicht vertrauenswürdigen Quelle zu gewähren (z. B. den Objekten NameTable, XmlNamespaceManager und XmlResolver).