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 undNmTokens
in einer einzelnenEnumeration
-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 |
Navigieren durch Knoten
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:
- GetAttribute
- MoveToAttribute
- MoveToFirstAttribute
- MoveToNextAttribute
- MoveToElement
- ReadAttributeValue
- ReadSubtree
- ResolveEntity
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:
Beschränken Sie die Ressourcen, auf die der XmlReader zugreifen kann, indem Sie die XmlReaderSettings.XmlResolver-Eigenschaft auf ein XmlSecureResolver-Objekt festlegen.
Wenn Sie die XmlReader-Eigenschaft auf XmlReaderSettings.XmlResolver festlegen, kann der
null
keine externen Ressourcen öffnen.
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).