Classe System.Xml.XmlReader

Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.

XmlReader fornisce l'accesso forward-only e di sola lettura ai dati XML in un documento o in un flusso. Questa classe è conforme alle raccomandazioni W3C Extensible Markup Language (XML) 1.0 (quarta edizione) e spazi dei nomi in XML 1.0 (terza edizione).

XmlReader i metodi consentono di spostarsi tra i dati XML e leggere il contenuto di un nodo. Le proprietà della classe riflettono il valore del nodo corrente, in cui è posizionato il lettore. Il ReadState valore della proprietà indica lo stato corrente del lettore XML. Ad esempio, la proprietà viene impostata su ReadState.Initial dal XmlReader.Read metodo e ReadState.Closed dal XmlReader.Close metodo . XmlReader fornisce inoltre controlli di conformità dei dati e convalida in base a una DTD o a uno schema.

XmlReader usa un modello di pull per recuperare i dati. Questo modello:

  • Semplifica la gestione dello stato mediante un perfezionamento procedurale naturale e dall'alto verso il basso.
  • Supporta più flussi di input e livelli.
  • Consente al client di assegnare al parser un buffer in cui la stringa viene scritta direttamente ed evita quindi la necessità di una copia di stringa aggiuntiva.
  • Supporta l'elaborazione selettiva. Il client può ignorare gli elementi ed elaborare quelli di interesse per l'applicazione. È anche possibile impostare in anticipo le proprietà per gestire la modalità di elaborazione del flusso XML, ad esempio la normalizzazione.

Creare un lettore XML

Usare il Create metodo per creare un'istanza XmlReader di .

Anche se .NET fornisce implementazioni concrete della XmlReader classe , ad esempio XmlTextReader, XmlNodeReadere le XmlValidatingReader classi , è consigliabile usare le classi specializzate solo in questi scenari:

  • Quando si desidera leggere un sottoalbero DOM XML da un XmlNode oggetto , usare la XmlNodeReader classe . Questa classe, tuttavia, non supporta la convalida DTD o dello schema.
  • Se è necessario espandere le entità su richiesta, non si vuole normalizzare il contenuto di testo o non si desidera che vengano restituiti attributi predefiniti, usare la XmlTextReader classe .

Per specificare il set di funzionalità che si desidera abilitare nel lettore XML, passare un System.Xml.XmlReaderSettings oggetto al Create metodo . È possibile usare un singolo System.Xml.XmlReaderSettings oggetto per creare più lettori con la stessa funzionalità o modificare l'oggetto System.Xml.XmlReaderSettings per creare un nuovo lettore con un set di funzionalità diverso. È anche possibile aggiungere facilmente funzionalità a un lettore esistente.

Se non si usa un System.Xml.XmlReaderSettings oggetto, vengono usate le impostazioni predefinite. Per informazioni dettagliate, vedere la Create pagina di riferimento.

XmlReader genera un oggetto XmlException sugli errori di analisi XML. Dopo la generazione di un'eccezione, lo stato del lettore non è prevedibile. Ad esempio, il tipo di nodo segnalato può essere diverso dal tipo di nodo effettivo del nodo corrente. Utilizzare la ReadState proprietà per verificare se il lettore è in stato di errore.

Convalidare i dati XML

Per definire la struttura di un documento XML e le relative relazioni tra elementi, tipi di dati e vincoli di contenuto, utilizzare uno schema XSD (Document Type Definition Language) o XML Schema Definition Language (XSD). Un documento XML viene considerato ben formato se soddisfa tutti i requisiti sintattici definiti dalla raccomandazione W3C XML 1.0. È considerato valido se è ben formato e conforme anche ai vincoli definiti dal DTD o dallo schema. (Vedere il W3C XML Schema Part 1: Structures and the W3C XML Schema Part 2: Datatypes recommendations.) Pertanto, anche se tutti i documenti XML validi sono ben formati, non tutti i documenti XML ben formati sono validi.

È possibile convalidare i dati in base a un DTD, a uno schema XSD inline o a uno schema XSD archiviato in un XmlSchemaSet oggetto (una cache). Questi scenari sono descritti nella pagina di Create riferimento. XmlReader non supporta la convalida dello schema XML-Data Reduced (XDR).

Usare le impostazioni seguenti nella XmlReaderSettings classe per specificare il tipo di convalida, se presente, supportato dall'istanza XmlReader .

Usare questo XmlReaderSettings membro Per specificare
Proprietà DtdProcessing Indica se consentire l'elaborazione DTD. Per impostazione predefinita l'elaborazione della DTD non è consentita.
Proprietà ValidationType Indica se il lettore deve convalidare i dati e quale tipo di convalida eseguire (DTD o schema). Per impostazione predefinita non è prevista alcuna convalida dei dati.
EventoValidationEventHandler Gestore eventi per la ricezione di informazioni sugli eventi di convalida. Se non si fornisce un gestore eventi, viene generata un'eccezione XmlException per il primo errore di convalida.
Proprietà ValidationFlags Opzioni di convalida aggiuntive tramite i membri dell'enumerazione XmlSchemaValidationFlags :

- AllowXmlAttributes-- Consenti attributi XML (xml:*) nei documenti dell'istanza anche quando non sono definiti nello schema. Gli attributi vengono convalidati in base al relativo tipo di dati. Vedere la XmlSchemaValidationFlags pagina di riferimento per l'impostazione da usare in scenari specifici. Disabilitato per impostazione predefinita.
- ProcessIdentityConstraints --Elaborare vincoli di identità (xs:ID, xs:IDREF, xs:key, xs:keyref, ) xs:uniquerilevati durante la convalida. Abilitata per impostazione predefinita.
- ProcessSchemaLocation Schemi --Process specificati dall'attributo xsi:schemaLocation o xsi:noNamespaceSchemaLocation . Abilitata per impostazione predefinita.
- ProcessInlineSchema-- Elaborare xml schema inline durante la convalida. Disabilitato per impostazione predefinita.
- ReportValidationWarnings--Segnala eventi se si verifica un avviso di convalida. Un avviso, in genere, viene emesso quando non si dispone di una DTD o di un XML Schema in base al quale convalidare un determinato elemento o attributo. L'evento ValidationEventHandler viene utilizzato per la notifica. Disabilitato per impostazione predefinita.
Schemas Oggetto XmlSchemaSet da usare per la convalida.
Proprietà XmlResolver Oggetto XmlResolver per la risoluzione e l'accesso alle risorse esterne. Può includere entità esterne, ad esempio DTD e schemi, e qualsiasi xs:include elemento o xs:import contenuto nello schema XML. Se non si specifica un oggetto XmlResolver, XmlReader usa un valore predefinito XmlUrlResolver senza credenziali utente.

Conformità dei dati

I lettori XML creati dal Create metodo soddisfano i requisiti di conformità seguenti per impostazione predefinita:

  • Le nuove righe e il valore dell'attributo vengono normalizzati in base alla raccomandazione W3C XML 1.0.

  • Tutte le entità vengono espanse automaticamente.

  • Gli attributi predefiniti dichiarati nella definizione del tipo di documento vengono sempre aggiunti anche quando il lettore non convalida.

  • È consentita la dichiarazione di prefisso XML mappato all'URI dello spazio dei nomi XML corretto.

  • I nomi di notazione in una singola NotationType dichiarazione di attributo e NmTokens in una singola Enumeration dichiarazione di attributo sono distinti.

Usare queste XmlReaderSettings proprietà per specificare il tipo di controlli di conformità da abilitare:

Utilizzare questa XmlReaderSettings proprietà Per Valori predefiniti
Proprietà CheckCharacters Abilitare o disabilitare i controlli per quanto segue:

- I caratteri sono compresi nell'intervallo di caratteri XML legali, come definito dalla sezione 2.2 Characters della raccomandazione W3C XML 1.0.
- Tutti i nomi XML sono validi, come definito dalla sezione 2.3 Costrutti sintattici comuni della raccomandazione W3C XML 1.0.

Quando questa proprietà è impostata su true (impostazione predefinita), viene generata un'eccezione XmlException se il file XML contiene caratteri non validi o nomi XML non validi, ad esempio un nome di elemento inizia con un numero.
Il controllo dei caratteri e dei nomi è abilitato.

Se si imposta la proprietà CheckCharacters su false, il controllo dei caratteri per i riferimenti a entità carattere viene disattivato. Se il lettore elabora dati di testo, verifica sempre che i nomi XML siano validi, indipendentemente da questa impostazione. Nota: la raccomandazione XML 1.0 richiede la conformità a livello di documento quando è presente un DTD. Pertanto, se il lettore è configurato per supportare ConformanceLevel.Fragment, ma i dati XML contengono una definizione del tipo di documento (DTD), viene generata un'eccezione XmlException .
Proprietà ConformanceLevel Scegliere il livello di conformità da applicare:

- Document. Conforme alle regole per un documento XML 1.0 ben formato.
- Fragment. È conforme alle regole per un frammento di documento ben formato che può essere utilizzato come entità analizzata esterna.
- Auto. Conforme al livello deciso dal lettore.

Se i dati non sono conformi, viene generata un'eccezione XmlException .
Document

Il nodo corrente è il nodo XML in cui è attualmente posizionato il lettore XML. Tutti i XmlReader metodi eseguono operazioni in relazione a questo nodo e tutte le XmlReader proprietà riflettono il valore del nodo corrente.

I metodi seguenti semplificano l'esplorazione dei nodi e l'analisi dei dati.

Utilizzare questo XmlReaderSettings metodo Per
Read Leggere il primo nodo e passare attraverso il flusso un nodo alla volta. Tali chiamate vengono in genere eseguite all'interno di un while ciclo.

Usare la NodeType proprietà per ottenere il tipo , ad esempio attributo, commento, elemento e così via, del nodo corrente.
Skip Ignorare gli elementi figlio del nodo corrente e passare al nodo successivo.
MoveToContent e MoveToContentAsync Ignorare i nodi non di contenuto e passare al nodo di contenuto successivo o alla fine del file.

I nodi non di contenuto includono ProcessingInstruction, DocumentTypeComment, Whitespace, e SignificantWhitespace.

I nodi del contenuto includono testo non vuoto, CDATA, EntityReference e EndEntity.
ReadSubtree Leggere un elemento e tutti i relativi elementi figlio e restituire una nuova XmlReader istanza impostata su ReadState.Initial.

Questo metodo è utile per la creazione di limiti intorno agli elementi XML; Ad esempio, se si desidera passare dati a un altro componente per l'elaborazione e si vuole limitare la quantità di dati a cui il componente può accedere.

Vedere la XmlReader.Read pagina di riferimento per un esempio di spostamento attraverso un flusso di testo un nodo alla volta e la visualizzazione del tipo di ogni nodo.

Le sezioni seguenti descrivono come leggere tipi specifici di dati, ad esempio elementi, attributi e dati tipiti.

Leggere elementi XML

Nella tabella seguente sono elencati i metodi e le proprietà forniti dalla classe per l'elaborazione XmlReader degli elementi. Dopo che il tipo XmlReader è stato posizionato in corrispondenza di un elemento, le proprietà del nodo, quale Name, riflettono i valori dell'elemento. Oltre ai membri descritti di seguito, è possibile utilizzare qualsiasi metodo e proprietà generale della classe XmlReader per elaborare gli elementi. Il metodo ReadInnerXml può essere utilizzato, ad esempio, per leggere il contenuto di un elemento.

Nota

Vedere la sezione 3.1 della raccomandazione W3C XML 1.0 per le definizioni dei tag di inizio, dei tag di fine e dei tag di elemento vuoti.

Usare questo XmlReader membro Per
Metodo IsStartElement Controllare se il nodo corrente è un tag di inizio o un tag di elemento vuoto.
Metodo ReadStartElement Verificare che il nodo corrente sia un elemento e passare il lettore al nodo successivo (chiamate IsStartElement seguite da Read).
Metodo ReadEndElement Verificare che il nodo corrente sia un tag di fine e passare il lettore al nodo successivo.
Metodo ReadElementString Consente di leggere un elemento di sola lettura.
Metodo ReadToDescendant Sposta il lettore XML sull'elemento discendente successivo (figlio) con il nome specificato.
Metodo ReadToNextSibling Sposta il lettore XML sull'elemento di pari livello successivo con il nome specificato.
Proprietà IsEmptyElement Controllare se l'elemento corrente ha un tag di elemento finale. Ad esempio:

- <item num="123"/> (IsEmptyElement è true.)
- <item num="123"> </item> (IsEmptyElement è false, anche se il contenuto dell'elemento è vuoto.

Per un esempio di lettura del contenuto di testo degli elementi, vedere il ReadString metodo . Nell'esempio seguente vengono elaborati gli elementi usando un while ciclo .

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

Leggere gli attributi XML

Gli attributi XML vengono comunemente trovati sugli elementi, ma sono consentiti anche nei nodi di dichiarazione XML e tipo di documento.

Quando posizionato su un nodo di elemento, il MoveToAttribute metodo consente di esaminare l'elenco di attributi dell'elemento. Si noti che dopo MoveToAttribute la chiamata, le proprietà del nodo, ad Nameesempio , NamespaceURIe Prefix riflettono le proprietà di tale attributo, non le proprietà dell'elemento a cui appartiene l'attributo.

La XmlReader classe fornisce questi metodi e proprietà per leggere ed elaborare attributi sugli elementi.

Usare questo XmlReader membro Per
Proprietà HasAttributes Controllare se il nodo corrente dispone di attributi.
Proprietà AttributeCount Ottiene il numero di attributi nell'elemento corrente.
Metodo MoveToFirstAttribute Passare al primo attributo in un elemento .
Metodo MoveToNextAttribute Passare all'attributo successivo in un elemento .
Metodo MoveToAttribute Passare a un attributo specificato.
GetAttribute metodo o Item[] proprietà Ottiene il valore di un attributo specificato.
Proprietà IsDefault Controllare se il nodo corrente è un attributo generato dal valore predefinito definito nello schema o DTD.
Metodo MoveToElement Passare all'elemento proprietario dell'attributo corrente. Utilizzare questo metodo per tornare a un elemento dopo lo spostamento tra i relativi attributi.
Metodo ReadAttributeValue Analizzare il valore dell'attributo in uno o più Textnodi , EntityReferenceo EndEntity .

Per elaborare gli attributi è possibile utilizzare anche qualsiasi metodo e proprietà generale del tipo XmlReader. Dopo che il tipo XmlReader è stato posizionato in corrispondenza di un attributo, ad esempio, le proprietà Name e Value riflettono i valori dell'attributo. È inoltre possibile utilizzare qualsiasi metodo Read del contenuto per ottenere il valore dell'attributo.

In questo esempio viene utilizzata la AttributeCount proprietà per spostarsi tra tutti gli attributi di un elemento.

// 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 questo esempio viene usato il MoveToNextAttribute metodo in un while ciclo per spostarsi tra gli attributi.

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

Lettura degli attributi nei nodi di dichiarazione XML

Quando il lettore XML è posizionato in un nodo di dichiarazione XML, la Value proprietà restituisce le informazioni sulla versione, sulla modalità autonoma e sulla codifica come singola stringa. XmlReader gli oggetti creati dal Create metodo, dalla XmlTextReader classe e dalla XmlValidatingReader classe espongono gli elementi di versione, autonomi e di codifica come attributi.

Lettura degli attributi nei nodi del tipo di documento

Quando il lettore XML è posizionato in un nodo del tipo di documento, è possibile utilizzare il metodo e Item[] la GetAttribute proprietà per restituire i valori per i valori letterali SYSTEM e PUBLIC. Ad esempio, la chiamata al metodo reader.GetAttribute("PUBLIC") restituisce il valore PUBLIC.

Lettura degli attributi nei nodi di istruzione di elaborazione

Quando il tipo XmlReader è posizionato in corrispondenza di un nodo di istruzioni di elaborazione, la proprietà Value restituisce l'intero contenuto di testo. Gli elementi nel nodo dell'istruzione di elaborazione non vengono considerati come attributi. Non possono essere letti con il GetAttribute metodo o MoveToAttribute .

Leggere il contenuto XML

La classe XmlReader include i membri seguenti che leggono il contenuto da un file XML e restituiscono il contenuto come valori stringa. Per restituire tipi CLR, vedere Convertire in tipi CLR.

Usare questo XmlReader membro Per
Proprietà Value Ottenere il contenuto di testo del nodo corrente. Il valore restituito dipende dal tipo di nodo; per informazioni dettagliate, vedere la Value pagina di riferimento.
Metodo ReadString Ottenere il contenuto di un elemento o di un nodo di testo come stringa. Questo metodo smette di elaborare istruzioni e commenti.

Per informazioni dettagliate su come questo metodo gestisce tipi di nodo specifici, vedere la pagina di ReadString riferimento.
Metodi ReadInnerXml e ReadInnerXmlAsync Ottenere tutto il contenuto del nodo corrente, incluso il markup, ma escludendo i tag di inizio e fine. Ad esempio, per:

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

ReadInnerXml Restituisce:

this<child id="123"/>
Metodi ReadOuterXml e ReadOuterXmlAsync Ottenere tutto il contenuto del nodo corrente e dei relativi elementi figlio, inclusi i tag di markup e inizio/fine. Ad esempio, per:

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

ReadOuterXml Restituisce:

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

Convertire in tipi CLR

È possibile usare i membri della XmlReader classe (elencati nella tabella seguente) per leggere i dati XML e restituire valori come tipi CLR (Common Language Runtime) anziché stringhe. Questi membri consentono di ottenere valori nella rappresentazione più appropriata per l'attività di codifica senza dover analizzare o convertire manualmente i valori stringa.

  • I metodi ReadElementContentAs possono essere chiamati solo sui tipi di nodo dell'elemento. e non possono essere utilizzati su elementi contenenti elementi figlio o contenuto misto. Quando viene chiamato, l'oggetto XmlReader legge il tag di inizio e il contenuto dell'elemento, quindi si sposta dopo il tag di fine dell'elemento. Le istruzioni di elaborazione e i commenti vengono ignorati e le entità vengono espanse.

  • I metodi ReadContentAs leggono il contenuto di testo nella posizione corrente del lettore e se ai dati XML non sono associate informazioni sullo schema o sul tipo di dati, convertire il contenuto di testo nel tipo restituito richiesto. Il testo, gli spazi vuoti, gli spazi vuoti significativi e le sezioni CDATA sono concatenati. I commenti e le istruzioni di elaborazione vengono ignorati e i riferimenti alle entità vengono risolti automaticamente.

La XmlReader classe usa le regole definite dalla raccomandazione W3C XML Schema Part 2: Datatypes .

Utilizzare questo XmlReader metodo Per restituire questo tipo CLR
ReadContentAsBoolean e ReadElementContentAsBoolean Boolean
ReadContentAsDateTime e ReadElementContentAsDateTime DateTime
ReadContentAsDouble e ReadElementContentAsDouble Double
ReadContentAsLong e ReadElementContentAsLong Int64
ReadContentAsInt e ReadElementContentAsInt Int32
ReadContentAsString e ReadElementContentAsString String
ReadContentAs e ReadElementContentAs Tipo specificato con il returnType parametro
ReadContentAsObject e ReadElementContentAsObject Tipo più appropriato, come specificato dalla XmlReader.ValueType proprietà . Per informazioni sul mapping, vedere Supporto dei tipi nelle classi System.Xml.

Se un elemento non può essere facilmente convertito in un tipo CLR a causa del relativo formato, è possibile usare un mapping dello schema per garantire una conversione corretta. Nell'esempio seguente viene utilizzato un file con estensione xsd per convertire l'elemento hire-date nel xs:date tipo e quindi viene utilizzato il metodo per restituire l'elemento ReadElementContentAsDateTime come DateTime oggetto .

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

Codice:

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

Output:

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

Programmazione asincrona

La maggior parte dei XmlReader metodi ha controparti asincrone che hanno "Async" alla fine dei nomi dei metodi. Ad esempio, l'equivalente asincrono di ReadContentAsObject è ReadContentAsObjectAsync.

I metodi seguenti possono essere usati con chiamate asincrone di metodi:

Le sezioni seguenti descrivono l'utilizzo asincrono per i metodi che non dispongono di controparti asincrone.

ReadStartElement, metodo

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

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

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

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

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

Considerazioni sulla sicurezza

Quando si lavora con la XmlReader classe , tenere presente quanto segue:

  • Le eccezioni generate da XmlReader possono divulgare informazioni sul percorso che potrebbero non essere necessarie per l'app. L'app deve intercettare le eccezioni ed elaborarle in modo appropriato.

  • Non abilitare l'elaborazione DTD se si è preoccupati per problemi denial of service o se si gestiscono origini non attendibili. L'elaborazione DTD è disabilitata per impostazione predefinita per XmlReader gli oggetti creati dal Create metodo .

    Se l'elaborazione della DTD è attivata, è possibile utilizzare il tipo XmlSecureResolver per limitare le risorse a cui il tipo XmlReader può accedere. È anche possibile progettare l'app in modo che l'elaborazione XML sia vincolata da memoria e tempo. Ad esempio, è possibile configurare i limiti di timeout nell'app ASP.NET.

  • È possibile che i dati XML includano riferimenti a risorse esterne quali, ad esempio, un file dello schema. Per impostazione predefinita, le risorse esterne vengono risolte usando un XmlUrlResolver oggetto senza credenziali utente. È possibile migliorare i livelli di sicurezza mediante una delle seguenti operazioni:

  • I ProcessInlineSchema flag di convalida e ProcessSchemaLocation di un XmlReaderSettings oggetto non sono impostati per impostazione predefinita. Ciò consente di proteggere il tipo XmlReader da attacchi basati sullo schema durante l'elaborazione dei dati XML da un'origine non attendibile. Se questi flag sono impostati, verrà utilizzata la proprietà XmlResolver dell'oggetto XmlReaderSettings per risolvere i percorsi dello schema rilevati nel documento di istanza nel tipo XmlReader. Se la XmlResolver proprietà è impostata su null, i percorsi dello schema non vengono risolti anche se vengono impostati i ProcessInlineSchema flag di convalida e ProcessSchemaLocation .

    Gli schemi aggiunti durante la convalida aggiungono nuovi tipi e possono alterare l'esito della convalida del documento in esame. Di conseguenza, gli schemi esterni devono essere risolti solo da origini attendibili.

    È consigliabile disabilitare il ProcessIdentityConstraints flag quando si convalidano documenti XML di grandi dimensioni non attendibili in scenari a disponibilità elevata rispetto a uno schema con vincoli di identità su una parte importante del documento. Questo flag è abilitato per impostazione predefinita.

  • I dati XML possono contenere un numero elevato di attributi, dichiarazione dello spazio dei nomi, elementi annidati e così via, la cui elaborazione richiede una notevole quantità di tempo. Per limitare le dimensioni dell'input inviato a XmlReader, è possibile:

  • Il ReadValueChunk metodo può essere usato per gestire flussi di dati di grandi dimensioni. Questo metodo consente di leggere un numero ridotto di caratteri alla volta invece di allocare una singola stringa per l'intero valore.

  • Quando si legge un documento XML con un numero elevato di nomi locali, spazi dei nomi o prefissi univoci, può verificarsi un problema. Se si usa una classe che deriva da XmlReadere si chiama la LocalNameproprietà , Prefixo NamespaceURI per ogni elemento, la stringa restituita viene aggiunta a un oggetto NameTable. La raccolta mantenuta da NameTable non riduce mai le dimensioni, creando una perdita di memoria virtuale degli handle di stringa. Una mitigazione di questo tipo consiste nel derivare dalla NameTable classe e applicare una quota di dimensioni massime. Non esiste alcun modo per impedire l'uso di un NameTableoggetto o per cambiare l'oggetto NameTable quando è pieno. Un'altra mitigazione consiste nell'evitare di usare le proprietà indicate e usare invece il MoveToAttribute metodo con il IsStartElement metodo laddove possibile. Tali metodi non restituiscono stringhe ed evitare quindi il problema di sovraccaricare la NameTable raccolta.

  • Gli oggetti XmlReaderSettings possono contenere informazioni sensibili quali le credenziali utente. L'oggetto XmlReaderSettings e le relative credenziali utente potrebbero essere utilizzate da un componente non attendibile per creare oggetti XmlReader che consentano di leggere i dati. Prestare attenzione quando si memorizzano nella cache XmlReaderSettings gli oggetti o quando si passa l'oggetto XmlReaderSettings da un componente a un altro.

  • Non accettare componenti di supporto, ad esempio oggetti NameTable, XmlNamespaceManager e XmlResolver da un'origine non attendibile.