Partager via


Classe System.Xml.XmlReader

Cet article fournit des remarques supplémentaires à la documentation de référence de cette API.

XmlReader fournit un accès en lecture seule aux données XML dans un document ou un flux. Cette classe est conforme aux recommandations W3C Extensible Markup Language (XML) 1.0 (quatrième édition) et aux espaces de noms dans les recommandations XML 1.0 (troisième édition).

XmlReader les méthodes vous permettent de parcourir les données XML et de lire le contenu d’un nœud. Les propriétés de la classe reflètent la valeur du nœud actuel, qui est l’emplacement du lecteur. La ReadState valeur de la propriété indique l’état actuel du lecteur XML. Par exemple, la propriété est définie ReadState.Initial par la XmlReader.Read méthode et ReadState.Closed par la XmlReader.Close méthode. XmlReader fournit également des vérifications et une validation de conformité des données sur un DTD ou un schéma.

XmlReader utilise un modèle d’extraction pour récupérer des données. Ce modèle :

  • Simplifie la gestion des états grâce à un raffinement procédural naturel et descendant.
  • Prend en charge plusieurs flux d'entrée et les superpositions.
  • Permet au client de donner à l’analyseur une mémoire tampon dans laquelle la chaîne est directement écrite, et évite ainsi la nécessité d’une copie de chaîne supplémentaire.
  • Prend en charge le traitement sélectif. Le client peut ignorer les éléments et traiter ceux qui sont intéressants pour l’application. Vous pouvez également définir des propriétés à l’avance pour gérer la façon dont le flux XML est traité (par exemple, normalisation).

Créer un lecteur XML

Utilisez la Create méthode pour créer une XmlReader instance.

Bien que .NET fournisse des implémentations concrètes de la XmlReader classe, telles que les XmlTextReaderclasses , XmlNodeReaderet les XmlValidatingReader classes, nous vous recommandons d’utiliser les classes spécialisées uniquement dans ces scénarios :

  • Lorsque vous souhaitez lire une sous-arborescence DOM XML à partir d’un XmlNode objet, utilisez la XmlNodeReader classe. (Toutefois, cette classe ne prend pas en charge la validation de schéma ou DTD.)
  • Si vous devez développer des entités à la demande, vous ne souhaitez pas que votre contenu texte soit normalisé ou que vous ne souhaitez pas que les attributs par défaut soient retournés, utilisez la XmlTextReader classe.

Pour spécifier l’ensemble de fonctionnalités que vous souhaitez activer sur le lecteur XML, transmettez un System.Xml.XmlReaderSettings objet à la Create méthode. Vous pouvez utiliser un seul System.Xml.XmlReaderSettings objet pour créer plusieurs lecteurs avec la même fonctionnalité, ou modifier l’objet System.Xml.XmlReaderSettings pour créer un lecteur avec un ensemble différent de fonctionnalités. Vous pouvez également ajouter facilement des fonctionnalités à un lecteur existant.

Si vous n’utilisez pas d’objet System.Xml.XmlReaderSettings , les paramètres par défaut sont utilisés. Pour plus d’informations, consultez la Create page de référence.

XmlReader lance un XmlException en cas d'erreur d'analyse XML. Une fois qu’une exception est levée, l’état du lecteur n’est pas prévisible. Par exemple, le type de nœud signalé peut être différent du type de nœud réel du nœud actuel. Utilisez la ReadState propriété pour vérifier si le lecteur est dans un état d’erreur.

Valider des données XML

Pour définir la structure d’un document XML et de ses relations d’éléments, types de données et contraintes de contenu, vous utilisez un schéma de définition de type de document (DTD) ou de langage XSD (XML Schema Definition Language). Un document XML est considéré comme bien formé s’il répond à toutes les exigences syntactiques définies par la recommandation W3C XML 1.0. Il est considéré comme valide s’il est bien formé et est également conforme aux contraintes définies par son DTD ou son schéma. (Consultez la partie 1 du schéma XML W3C : Structures et la partie 2 du schéma XML W3C : Recommandations sur les types de données .) Par conséquent, bien que tous les documents XML valides soient bien formés, tous les documents XML bien formés ne sont pas valides.

Vous pouvez valider les données sur un DTD, un schéma XSD inline ou un schéma XSD stocké dans un XmlSchemaSet objet (un cache) ; ces scénarios sont décrits sur la Create page de référence. XmlReader ne prend pas en charge la validation du schéma XML-Data Reduced (XDR).

Vous utilisez les paramètres suivants de la classe XmlReaderSettings pour spécifier quel type de validation, si l'instance XmlReader en supporte, est pris en charge.

Utilisez ce membre XmlReaderSettings Pour spécifier
Propriété DtdProcessing Indique s’il faut autoriser le traitement DTD. La valeur par défaut consiste à interdire le traitement DTD.
Propriété ValidationType Indique si le lecteur doit valider les données et quel type de validation effectuer (DTD ou schéma). La valeur par défaut est l'absence de validation des données.
ValidationEventHandler événement Gestionnaire d’événements pour recevoir des informations sur les événements de validation. Si un gestionnaire d’événements n’est pas fourni, un XmlException est levé lors de la première erreur de validation.
Propriété ValidationFlags Options de validation supplémentaires via les membres de l’énumération XmlSchemaValidationFlags :

- AllowXmlAttributes-- Autoriser les attributs XML (xml:*) dans les documents d’instance, même lorsqu’ils ne sont pas définis dans le schéma. Les attributs sont validés en fonction de leur type de données. Consultez la XmlSchemaValidationFlags page de référence du paramètre à utiliser dans des scénarios spécifiques. (Désactivé par défaut.)
- ProcessIdentityConstraints --Contraintes d’identité de processus (xs:ID, xs:IDREF, xs:key, xs:keyref, xs:unique) rencontrés lors de la validation. (Activé par défaut.)
- ProcessSchemaLocation --Traiter les schémas spécifiés par l'attribut xsi:schemaLocation ou l'attribut xsi:noNamespaceSchemaLocation. (Activé par défaut.)
- ProcessInlineSchema-- Traiter les schémas XML inline lors de la validation. (Désactivé par défaut.)
- ReportValidationWarnings--Signaler les événements si un avertissement de validation se produit. Un avertissement est généralement émis lorsqu’il n’existe aucun schéma DTD ou XML pour valider un élément ou un attribut particulier. Le ValidationEventHandler est utilisé pour la notification. (Désactivé par défaut.)
Schemas XmlSchemaSet à utiliser pour la validation.
Propriété XmlResolver XmlResolver pour la résolution et l'accès aux ressources externes. Cela peut inclure des entités externes telles que DTD et des schémas, ainsi que tous xs:include les éléments xs:import contenus dans le schéma XML. Si vous ne spécifiez pas d’informations d’identification utilisateur XmlResolver, le paramètre XmlReader utilise une valeur par défaut XmlUrlResolver sans informations d’identification utilisateur.

Conformité des données

Les lecteurs XML créés par la Create méthode répondent aux exigences de conformité suivantes par défaut :

  • Les nouvelles lignes et la valeur d’attribut sont normalisées conformément à la recommandation W3C XML 1.0.

  • Toutes les entités sont automatiquement étendues.

  • Les attributs par défaut déclarés dans la définition de type de document sont toujours ajoutés même lorsque le lecteur ne valide pas.

  • La déclaration du préfixe XML mappé à l’URI d’espace de noms XML correct est autorisée.

  • Les noms de notation dans une déclaration d’attribut unique NotationType et NmTokens dans une seule déclaration d’attribut Enumeration sont distincts.

Utilisez ces XmlReaderSettings propriétés pour spécifier le type de vérification de conformité que vous souhaitez activer :

Utiliser cette XmlReaderSettings propriété À Par défaut
Propriété CheckCharacters Activez ou désactivez les vérifications suivantes :

- Les caractères se trouvent dans la plage de caractères XML juridiques, comme défini par la section 2.2 Caractères de la recommandation W3C XML 1.0.
- Tous les noms XML sont valides, comme défini par la section 2.3 Constructions syntactiques communes de la recommandation W3C XML 1.0.

Lorsque cette propriété est définie true sur (valeur par défaut), une exception est levée si le fichier XML contient des caractères non valides ou des noms XML non valides (par exemple, un nom d’élément XmlException commence par un nombre).
La vérification des caractères et des noms est activée.

La définition de CheckCharacters à false désactive la vérification des caractères pour les références d'entités de caractères. Si le lecteur traite les données de texte, il vérifie toujours que les noms XML sont valides, quel que soit ce paramètre. Note: La recommandation XML 1.0 nécessite une conformité au niveau du document lorsqu’une DTD est présente. Par conséquent, si le lecteur est configuré pour prendre en charge ConformanceLevel.Fragment, mais que les données XML contiennent une définition de type de document (DTD), une XmlException est déclenchée.
Propriété ConformanceLevel Choisissez le niveau de conformité à appliquer :

- Document. Conforme aux règles d’un document XML 1.0 bien formé.
- Fragment. Conforme aux règles d’un fragment de document bien formé qui peut être consommé en tant qu’entité analysée externe.
- Auto. Conforme au niveau décidé par le lecteur.

Si les données ne sont pas conformes, une XmlException exception est levée.
Document

Le nœud actuel est le nœud XML sur lequel le lecteur XML est actuellement positionné. Toutes les méthodes effectuent des XmlReader opérations par rapport à ce nœud, et toutes les XmlReader propriétés reflètent la valeur du nœud actuel.

Les méthodes suivantes facilitent la navigation dans les nœuds et analysent les données.

Utiliser cette XmlReaderSettings méthode À
Read Lisez le premier nœud et passez par le flux un à la fois. Ces appels sont généralement effectués à l’intérieur d’une while boucle.

Utilisez la NodeType propriété pour obtenir le type (par exemple, attribut, commentaire, élément, et ainsi de suite) du nœud actuel.
Skip Ignorez les enfants du nœud actuel et passez au nœud suivant.
MoveToContent et MoveToContentAsync Ignorez les nœuds non-contenu et passez au nœud de contenu suivant ou à la fin du fichier.

Les nœuds non-contenu incluent ProcessingInstruction, , DocumentTypeComment, Whitespace, et SignificantWhitespace.

Les nœuds de contenu incluent du texte d’espace non blanc, CDATA, EntityReference et EndEntity.
ReadSubtree Lisez un élément et tous ses enfants, puis retournez une nouvelle XmlReader instance définie sur ReadState.Initial.

Cette méthode est utile pour créer des limites autour des éléments XML ; par exemple, si vous souhaitez transmettre des données à un autre composant pour le traitement et que vous souhaitez limiter la quantité de vos données que le composant peut accéder.

Consultez la XmlReader.Read page de référence pour obtenir un exemple de navigation dans un flux de texte d’un nœud à la fois et d’affichage du type de chaque nœud.

Les sections suivantes décrivent comment vous pouvez lire des types de données spécifiques, tels que des éléments, des attributs et des données typées.

Lire des éléments XML

Le tableau suivant répertorie les méthodes et les propriétés que la XmlReader classe fournit pour le traitement des éléments. Une fois l’élément XmlReader positionné sur un élément, les propriétés du nœud, telles que Name, reflètent les valeurs de l’élément. En plus des membres décrits ci-dessous, toutes les méthodes et propriétés générales de la XmlReader classe peuvent également être utilisées pour traiter des éléments. Par exemple, vous pouvez utiliser la ReadInnerXml méthode pour lire le contenu d’un élément.

Remarque

Consultez la section 3.1 de la recommandation W3C XML 1.0 pour les définitions des balises de début, des balises de fin et des balises d’élément vides.

Utilisez ce membre XmlReader À
méthode IsStartElement Vérifiez si le nœud actuel est une balise de début ou une balise d’élément vide.
méthode ReadStartElement Vérifiez que le nœud actuel est un élément et avancez le lecteur vers le nœud suivant (appels IsStartElement suivis par Read).
méthode ReadEndElement Vérifiez que le nœud actuel est une balise de fin et passez le lecteur au nœud suivant.
méthode ReadElementString Lire un élément texte uniquement.
méthode ReadToDescendant Avancez le lecteur XML vers l’élément descendant (enfant) suivant qui a le nom spécifié.
méthode ReadToNextSibling Avancez le lecteur XML vers l’élément frère suivant qui a le nom spécifié.
Propriété IsEmptyElement Vérifiez si l’élément actuel a une balise de fin. Par exemple:

- <item num="123"/> (IsEmptyElement est true.)
- <item num="123"> </item> (IsEmptyElement est false, bien que le contenu de l’élément soit vide.)

Pour obtenir un exemple de lecture du contenu texte d’éléments, consultez la ReadString méthode. L’exemple suivant traite les éléments à l’aide d’une while boucle.

while (reader.Read()) {
  if (reader.IsStartElement()) {
    if (reader.IsEmptyElement)
                {
                    Console.WriteLine($"<{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

Lire les attributs XML

Les attributs XML sont les plus couramment trouvés sur les éléments, mais ils sont également autorisés sur les nœuds de déclaration XML et de type de document.

Lorsqu’elle est positionnée sur un nœud d’élément, la MoveToAttribute méthode vous permet de parcourir la liste d’attributs de l’élément. Notez qu’après MoveToAttribute avoir été appelées, les propriétés de nœud telles que Name, NamespaceURIet Prefix reflètent les propriétés de cet attribut, et non les propriétés de l’élément auquel appartient l’attribut.

La XmlReader classe fournit ces méthodes et propriétés pour lire et traiter des attributs sur des éléments.

Utilisez ce membre XmlReader À
Propriété HasAttributes Vérifiez si le nœud actuel a des attributs.
Propriété AttributeCount Obtenez le nombre d’attributs sur l’élément actuel.
méthode MoveToFirstAttribute Accédez au premier attribut d’un élément.
méthode MoveToNextAttribute Passez à l’attribut suivant dans un élément.
méthode MoveToAttribute Passez à un attribut spécifié.
GetAttribute méthode ou Item[] propriété Obtient la valeur d’un attribut spécifié.
Propriété IsDefault Vérifiez si le nœud actuel est un attribut généré à partir de la valeur par défaut définie dans le DTD ou le schéma.
méthode MoveToElement Accédez à l’élément propriétaire de l’attribut actuel. Utilisez cette méthode pour revenir à un élément après avoir parcouru ses attributs.
méthode ReadAttributeValue Analysez la valeur d’attribut en un ou plusieurs nœuds Text, EntityReference ou EndEntity.

Toutes les méthodes et propriétés générales XmlReader peuvent également être utilisées pour traiter les attributs. Par exemple, après que le XmlReader est positionné sur un attribut, les propriétés Name et Value reflètent les valeurs de l’attribut. Vous pouvez également utiliser l’une des méthodes de contenu Read pour obtenir la valeur de l’attribut.

Cet exemple utilise la AttributeCount propriété pour parcourir tous les attributs d’un élément.

// Display all attributes.
if (reader.HasAttributes) {
  Console.WriteLine("Attributes of <" + reader.Name + ">");
  for (int i = 0; i < reader.AttributeCount; i++) {
    Console.WriteLine($"  {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

Cet exemple utilise la MoveToNextAttribute méthode dans une while boucle pour parcourir les attributs.

if (reader.HasAttributes) {
  Console.WriteLine("Attributes of <" + reader.Name + ">");
  while (reader.MoveToNextAttribute()) {
    Console.WriteLine($" {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

Lecture d’attributs sur des nœuds de déclaration XML

Lorsque le lecteur XML est positionné sur un nœud de déclaration XML, la Value propriété retourne les informations de version, autonomes et d’encodage sous forme de chaîne unique. Les objets XmlReader créés par la méthode Create, la classe XmlTextReader et la classe XmlValidatingReader exposent les éléments version, standalone et encoding en tant qu’attributs.

Lecture des attributs sur les nœuds de type document

Lorsque le lecteur XML est positionné sur un nœud de type de document, la méthode GetAttribute et la propriété Item[] peuvent être utilisées pour renvoyer les valeurs des littéraux SYSTEM et PUBLIC. Par exemple, l’appel reader.GetAttribute("PUBLIC") retourne la valeur PUBLIC.

Lire les attributs sur les nœuds d'instructions de traitement

Lorsque la XmlReader propriété est positionnée sur un nœud d’instruction de traitement, la Value propriété retourne tout le contenu du texte. Les éléments du nœud d’instruction de traitement ne sont pas traités comme des attributs. Ils ne peuvent pas être lus avec la méthode GetAttribute ou MoveToAttribute.

Lire du contenu XML

La classe XmlReader inclut les membres suivants qui lisent le contenu à partir d’un fichier XML et retournent le contenu sous forme de valeurs de chaîne. (Pour retourner des types CLR, consultez Convertir en types CLR.)

Utilisez ce membre XmlReader À
Propriété Value Obtenez le contenu texte du nœud actuel. La valeur retournée dépend du type de nœud ; consultez la page de référence pour plus d’informations Value .
méthode ReadString Obtenez le contenu d’un nœud d’élément ou de texte sous forme de chaîne. Cette méthode cesse de traiter les instructions et les commentaires.

Pour plus d’informations sur la façon dont cette méthode gère des types de nœuds spécifiques, consultez la ReadString page de référence.
Méthodes ReadInnerXml et ReadInnerXmlAsync Obtenez tout le contenu du nœud actuel, y compris le balisage, mais à l’exclusion des balises de début et de fin. Par exemple, pour :

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

ReadInnerXml retourne :

this<child id="123"/>
Méthodes ReadOuterXml et ReadOuterXmlAsync Obtenez tout le contenu du nœud actuel et de ses enfants, y compris les balises de balisage et de début/fin. Par exemple, pour :

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

ReadOuterXml retourne :

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

Conversion en types CLR

Vous pouvez utiliser les membres de la XmlReader classe (répertoriés dans le tableau suivant) pour lire des données XML et retourner des valeurs en tant que types CLR (Common Language Runtime) au lieu de chaînes. Ces membres vous permettent d’obtenir des valeurs dans la représentation qui convient le mieux à votre tâche de codage sans avoir à analyser ou convertir manuellement des valeurs de chaîne.

  • Les méthodes ReadElementContentAs ne peuvent être appelées que sur les types de nœuds d’élément. Ces méthodes ne peuvent pas être utilisées sur des éléments qui contiennent des éléments enfants ou du contenu mixte. Lorsqu’il est appelé, l’objet XmlReader lit la balise de début, lit le contenu de l’élément, puis se déplace au-delà de la balise d’élément final. Les instructions de traitement et les commentaires sont ignorés et les entités sont développées.

  • Les méthodes ReadContentAs lisent le contenu du texte à la position actuelle du lecteur et, si les données XML n’ont pas de schéma ni d’informations de type de données associées, convertissez le contenu du texte en type de retour demandé. Le texte, l’espace blanc, les espaces blancs significatifs et les sections CDATA sont concaténés. Les instructions de commentaires et de traitement sont ignorées et les références d’entité sont automatiquement résolues.

La XmlReader classe utilise les règles définies par la recommandation W3C XML Schema Part 2 : Datatypes recommandation.

Utiliser cette XmlReader méthode Pour renvoyer ce type CLR
ReadContentAsBoolean et ReadElementContentAsBoolean Boolean
ReadContentAsDateTime et ReadElementContentAsDateTime DateTime
ReadContentAsDouble et ReadElementContentAsDouble Double
ReadContentAsLong et ReadElementContentAsLong Int64
ReadContentAsInt et ReadElementContentAsInt Int32
ReadContentAsString et ReadElementContentAsString String
ReadContentAs et ReadElementContentAs Type que vous spécifiez avec le returnType paramètre
ReadContentAsObject et ReadElementContentAsObject Type le plus approprié, tel que spécifié par la XmlReader.ValueType propriété. Consultez la prise en charge des types dans les classes System.Xml pour obtenir des informations de mappage.

Si un élément ne peut pas facilement être converti en type CLR en raison de son format, vous pouvez utiliser un mappage de schéma pour garantir une conversion réussie. L’exemple suivant utilise un fichier .xsd pour convertir l’élément hire-date en xs:date type, puis utilise la ReadElementContentAsDateTime méthode pour renvoyer l’élément en tant qu’objet DateTime .

Entrée (hireDate.xml) :

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

Schéma (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: {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

Résultat :

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

Programmation asynchrone

La plupart des XmlReader méthodes ont des équivalents asynchrones qui ont « Async » à la fin de leurs noms de méthode. Par exemple, l’équivalent asynchrone est ReadContentAsObjectReadContentAsObjectAsync.

Les méthodes suivantes peuvent être utilisées avec des appels de méthode asynchrones :

Les sections suivantes décrivent l’utilisation asynchrone des méthodes qui n’ont pas d’équivalents asynchrones.

Méthode ReadStartElement

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

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

Méthode ReadEndElement

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

Méthode ReadToNextSibling

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

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

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

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

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

    ' find the next sibling
    Dim nt As XmlNodeType
    Do

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

    Return False

End Function

Méthode ReadToFollowing

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

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

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

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

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

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

    Return False
End Function

méthode ReadToDescendant

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

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

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

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

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

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

    Return False
End Function

Considérations relatives à la sécurité

Tenez compte des éléments suivants lors de l’utilisation de la XmlReader classe :

  • Les exceptions générées par XmlReader peuvent révéler des informations sur le chemin d'accès que vous n'aimeriez pas voir apparaître dans votre application. Votre application doit intercepter les exceptions et les traiter de manière appropriée.

  • N’activez pas le traitement DTD si vous êtes préoccupé par les problèmes de déni de service ou si vous traitez avec des sources non approuvées. Le traitement DTD est désactivé par défaut pour XmlReader les objets créés par la Create méthode.

    Si le traitement DTD est activé, vous pouvez utiliser la XmlSecureResolver méthode pour restreindre les ressources auxquelles l’accès XmlReader est possible. Vous pouvez également concevoir votre application afin que le traitement XML soit limité en mémoire et en temps. Par exemple, vous pouvez configurer des limites de délai d’attente dans votre application ASP.NET.

  • Les données XML peuvent inclure des références à des ressources externes telles qu’un fichier de schéma. Par défaut, les ressources externes sont résolues à l’aide d’un XmlUrlResolver objet sans informations d’identification utilisateur. Vous pouvez le sécuriser davantage en effectuant l’une des opérations suivantes :

  • Les indicateurs de validation ProcessInlineSchema et ProcessSchemaLocation d'un objet XmlReaderSettings ne sont pas activés par défaut. Cela permet de protéger le XmlReader contre les attaques basées sur des schémas lorsqu'il traite des données XML à partir d'une source non approuvée. Lorsque ces indicateurs sont activés, la propriété XmlResolver de l'objet XmlReaderSettings est utilisée pour résoudre les emplacements de schéma rencontrés dans le document d'instance dans l'objet XmlReader. Si la propriété XmlResolver est définie sur null, les emplacements de schéma ne sont pas résolus même si les indicateurs de validation ProcessInlineSchema et ProcessSchemaLocation sont définis.

    Les schémas ajoutés lors de la validation ajoutent de nouveaux types et peuvent modifier le résultat de validation du document en cours de validation. Par conséquent, les schémas externes ne doivent être résolus qu’à partir de sources approuvées.

    Nous vous recommandons de désactiver l’indicateur ProcessIdentityConstraints lors de la validation de documents XML non approuvés dans des scénarios de haute disponibilité sur un schéma qui a des contraintes d’identité sur une grande partie du document. Cet indicateur est activé par défaut.

  • Les données XML peuvent contenir un grand nombre d’attributs, de déclarations d’espace de noms, d’éléments imbriqués, et ainsi de suite, qui nécessitent un temps important de traitement. Pour limiter la taille de l’entrée envoyée au XmlReader, vous pouvez :

    • Limitez la taille du document en définissant la MaxCharactersInDocument propriété.

    • Limitez le nombre de caractères résultant du développement d’entités en définissant la MaxCharactersFromEntities propriété.

    • Créez une implémentation personnalisée IStream pour le XmlReader.

  • La ReadValueChunk méthode peut être utilisée pour gérer de grands flux de données. Cette méthode lit un petit nombre de caractères à la fois au lieu d’allouer une seule chaîne pour la valeur entière.

  • Lors de la lecture d’un document XML avec un grand nombre de noms locaux uniques, d’espaces de noms ou de préfixes, un problème peut se produire. Si vous utilisez une classe qui dérive de XmlReader et que vous appelez les propriétés LocalName, Prefix ou NamespaceURI pour chaque élément, la chaîne retournée est ajoutée à un NameTable. La taille de la collection contenue dans NameTable ne diminue jamais, ce qui crée une fuite de mémoire virtuelle des chaînes de caractères. Une atténuation pour cela consiste à dériver de la NameTable classe et à appliquer un quota de taille maximale. (Il n’existe aucun moyen d’empêcher l’utilisation d’un NameTable, ou de changer le NameTable moment où il est plein). Une autre solution consiste à éviter d'utiliser les propriétés mentionnées et à préférer la méthode MoveToAttribute avec la méthode IsStartElement lorsque cela est possible ; ces méthodes ne retournent pas de chaînes et évitent ainsi le problème de surcharge de la collection NameTable.

  • XmlReaderSettings les objets peuvent contenir des informations sensibles telles que des informations d’identification utilisateur. Un composant non approuvé peut utiliser l’objet XmlReaderSettings et ses informations d’identification utilisateur pour créer XmlReader des objets pour lire des données. Soyez prudent lors de la mise en cache d’objets XmlReaderSettings ou lors du passage de l’objet XmlReaderSettings d’un composant à un autre.

  • N’acceptez pas les composants de prise en charge, tels que les objets NameTable, XmlNamespaceManager et XmlResolver, à partir d’une source non approuvée.