Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.
XmlReader consente l'accesso forward-only e di sola lettura ai dati XML in un documento o in un flusso. Questa classe è conforme alle raccomandazioni del W3C Extensible Markup Language (XML) 1.0 (quarta edizione) e alle raccomandazioni di Namespaces in XML 1.0 (terza edizione).
XmlReader metodi consentono di spostarsi tra 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 valore della proprietà ReadState indica lo stato corrente del lettore XML. Ad esempio, la proprietà viene impostata su ReadState.Initial dal metodo XmlReader.Read e ReadState.Closed dal metodo XmlReader.Close. XmlReader fornisce anche controlli e convalida della conformità dei dati rispetto a un 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ò saltare gli elementi ed elaborare quelli che sono 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 metodo Create per creare un'istanza di XmlReader.
Anche se .NET fornisce implementazioni concrete della classe XmlReader, ad esempio XmlTextReader, XmlNodeReadere le classi XmlValidatingReader, è consigliabile usare le classi specializzate solo in questi scenari:
- Quando si desidera leggere un sottoalbero DOM XML da un oggetto XmlNode, utilizzare la classe XmlNodeReader. 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 classe XmlTextReader.
Per specificare il set di funzionalità che si desidera abilitare nel lettore XML, passare un oggetto System.Xml.XmlReaderSettings al metodo Create. È possibile usare un singolo oggetto System.Xml.XmlReaderSettings per creare più lettori con la stessa funzionalità oppure 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 oggetto System.Xml.XmlReaderSettings, vengono usate le impostazioni predefinite. Per informazioni dettagliate, vedere la pagina di riferimento Create.
XmlReader genera un XmlException per errori di analisi XML. Dopo il lancio 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 proprietà ReadState 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 dall'raccomandazione W3C XML 1.0. È considerato valido se è ben formato e conforme anche ai vincoli definiti dal DTD o dallo schema. Vedere le raccomandazioni W3C XML Schema Part 1: Structures e le raccomandazioni W3C XML Schema Part 2: Datatypes. 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 oggetto XmlSchemaSet (una cache); questi scenari sono descritti nella pagina di riferimento Create. XmlReader non supporta la convalida dello schema ridotta (XDR) XML-Data.
Utilizzi le impostazioni seguenti nella classe XmlReaderSettings per specificare quale tipo di convalida l'istanza di XmlReader supporta, se presente.
| Usa questo membro XmlReaderSettings | Per specificare |
|---|---|
| DtdProcessing proprietà | Indica se consentire l'elaborazione DTD. Il valore predefinito è non consentire l'elaborazione DTD. |
| ValidationType proprietà | Indica se il lettore deve convalidare i dati e quale tipo di convalida eseguire (DTD o schema). L'impostazione predefinita è di non avere convalida dei dati. |
| evento ValidationEventHandler | Gestore eventi per la ricezione di informazioni sugli eventi di convalida. Se non viene specificato un gestore eventi, viene generata una XmlException al primo errore di convalida. |
| ValidationFlags proprietà | 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 tipo di dati. Vedere la pagina di riferimento XmlSchemaValidationFlags per l'impostazione da usare in scenari specifici. Disabilitato per impostazione predefinita.- ProcessIdentityConstraints --Processo di vincoli di identità (xs:ID, xs:IDREF, xs:key, xs:keyref, xs:unique) rilevati durante la convalida. Abilitata per impostazione predefinita.- ProcessSchemaLocation Processa gli schemi specificati dall'attributo xsi:schemaLocation o xsi:noNamespaceSchemaLocation. Abilitata per impostazione predefinita.- ProcessInlineSchema-- Elaborare gli XML Schema inline durante la convalida. Disabilitato per impostazione predefinita.- ReportValidationWarnings--Riportare eventi se si verifica un avviso di convalida. Un avviso viene in genere generato quando non è presente alcun DTD o XML Schema per convalidare un particolare elemento o attributo rispetto a . Il ValidationEventHandler viene usato per la notifica. Disabilitato per impostazione predefinita. |
| Schemas | XmlSchemaSet da usare per la convalida. |
| XmlResolver proprietà | Il XmlResolver per risolvere e accedere alle risorse esterne. Ciò può includere entità esterne, ad esempio DTD e schemi, e qualsiasi xs:include o xs:import elementi contenuti in XML Schema. Se non si specifica un XmlResolver, il XmlReader usa un XmlUrlResolver predefinito senza credenziali utente. |
Conformità dei dati
I lettori XML creati dal metodo Create 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 dichiarazione di attributo
NotationTypeeNmTokensin una singola dichiarazione di attributoEnumerationsono distinti.
Usare queste proprietà XmlReaderSettings per specificare il tipo di controlli di conformità da abilitare:
| Utilizzare questa proprietà XmlReaderSettings | Per | Impostazione predefinita |
|---|---|---|
| CheckCharacters proprietà | Abilitare o disabilitare i controlli per quanto segue: - I caratteri sono compresi nell'intervallo di caratteri XML legali, come definito dalla sezione caratteri 2.2 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. L'impostazione di CheckCharacters su false disattiva il controllo dei caratteri per i riferimenti all'entità carattere. 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 una XmlException. |
| ConformanceLevel proprietà | 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 |
Navigare attraverso i nodi
Il nodo corrente è il nodo XML in cui è attualmente posizionato il lettore XML. Tutti i metodi XmlReader eseguono operazioni in relazione a questo nodo e tutte le proprietà XmlReader riflettono il valore del nodo corrente.
I metodi seguenti semplificano l'esplorazione dei nodi e l'analisi dei dati.
| Utilizzare questo metodo XmlReaderSettings | 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 ciclo while.Utilizzare la proprietà NodeType per ottenere il tipo (ad esempio, attributo, commento, elemento e così via) del nodo corrente. |
| Skip | Saltare 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, DocumentType, Comment, Whitespacee SignificantWhitespace. I nodi del contenuto includono testo non vuoto, CDATA, EntityReference e EndEntity. |
| ReadSubtree | Leggere un elemento e tutti i relativi elementi figli, e restituire una nuova istanza di XmlReader impostata a 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 pagina di riferimento XmlReader.Read per un esempio di esplorazione di 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 XmlReader per l'elaborazione degli elementi. Dopo che il XmlReader è posizionato su un elemento, le proprietà del nodo, ad esempio Name, riflettono i valori dell'elemento. Oltre ai membri descritti di seguito, è anche possibile usare i metodi e le proprietà generali della classe XmlReader per elaborare gli elementi. Ad esempio, è possibile usare il metodo ReadInnerXml per leggere il contenuto di un elemento.
Nota
Vedere la sezione 3.1 del raccomandazione W3C XML 1.0 per le definizioni dei tag di inizio, dei tag di fine e dei tag di elemento vuoti.
| Usa questo membro XmlReader | 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 far avanzare il lettore al nodo successivo (chiama IsStartElement seguito da Read). |
| Metodo ReadEndElement | Verificare che il nodo corrente sia un tag di fine e passare il lettore al nodo successivo. |
| Metodo ReadElementString | Leggi un elemento solo testo. |
| 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. |
| IsEmptyElement proprietà | Controllare se l'elemento corrente ha un tag di elemento finale. Per 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 metodo ReadString. Nell'esempio seguente vengono elaborati gli elementi usando un ciclo while.
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
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 metodo MoveToAttribute consente di esaminare l'elenco di attributi dell'elemento. Si noti che dopo che MoveToAttribute è stato chiamato, le proprietà del nodo, ad esempio Name, NamespaceURIe Prefix riflettono le proprietà di tale attributo, non le proprietà dell'elemento a cui appartiene l'attributo.
La classe XmlReader fornisce questi metodi e proprietà per leggere ed elaborare attributi sugli elementi.
| Usa questo membro XmlReader | Per |
|---|---|
| HasAttributes proprietà | Controllare se il nodo corrente dispone di attributi. |
| AttributeCount proprietà | Ottiene il numero di attributi nell'elemento corrente. |
| Metodo MoveToFirstAttribute | Passare al primo attributo dell'elemento. |
| Metodo MoveToNextAttribute | Passare all'attributo successivo in un elemento . |
| Metodo MoveToAttribute | Passare a un attributo specificato. |
| GetAttribute metodo o proprietà di Item[] | Ottiene il valore di un attributo specificato. |
| IsDefault proprietà | 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ù nodi Text, EntityReferenceo EndEntity. |
Per elaborare gli attributi, è possibile usare anche i metodi e le proprietà XmlReader generali. Ad esempio, dopo che il XmlReader è posizionato su un attributo, le proprietà Name e Value riflettono i valori dell'attributo. È anche possibile usare uno dei metodi Read del contenuto per ottenere il valore dell'attributo.
In questo esempio viene utilizzata la proprietà AttributeCount 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($" {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 metodo MoveToNextAttribute in un ciclo while per spostarsi tra gli attributi.
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
Lettura degli attributi nei nodi di dichiarazione XML
Quando il lettore XML viene posizionato in un nodo di dichiarazione XML, la proprietà Value restituisce le informazioni sulla versione, sulla versione autonoma e sulla codifica come singola stringa. XmlReader oggetti creati dal metodo Create, dalla classe XmlTextReader e dalla classe XmlValidatingReader espongono la versione, la versione autonoma e gli elementi 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 GetAttribute e la proprietà Item[] per restituire i valori per i valori letterali SYSTEM e PUBLIC. Ad esempio, la chiamata a reader.GetAttribute("PUBLIC") restituisce il valore PUBLIC.
Lettura degli attributi nei nodi di istruzione di elaborazione
Quando il XmlReader viene posizionato su 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 metodo GetAttribute 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.)
| Usa questo membro XmlReader | Per |
|---|---|
| Value proprietà | Ottenere il contenuto di testo del nodo corrente. Il valore restituito dipende dal tipo di nodo; per informazioni dettagliate, vedere la pagina di riferimento Value. |
| 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 riferimento ReadString. |
| 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 ritorna: this<child id="123"/> |
| metodi ReadOuterXml e ReadOuterXmlAsync | Recupera tutto il contenuto del nodo corrente e dei relativi elementi figlio, inclusi i tag di markup e di apertura/chiusura. Ad esempio, per:<node>this<child id="123"/></node>ReadOuterXml ritorna: <node>this<child id="123"/></node> |
Convertire in tipi CLR
È possibile usare i membri della classe XmlReader (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 elemento. Questi metodi non possono essere utilizzati su elementi che contengono elementi figli o contenuto misto. Quando viene chiamato, l'oggetto XmlReader legge il tag iniziale, legge il contenuto dell'elemento e quindi passa oltre il tag dell'elemento finale. 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 i dati XML non dispongono di informazioni sullo schema o sul tipo di dati associate, convertono il contenuto di testo nel tipo di ritorno richiesto. Testo, spazi vuoti, spazi vuoti significativi e sezioni CDATA vengono concatenati. I commenti e le istruzioni di elaborazione vengono ignorati e i riferimenti alle entità vengono risolti automaticamente.
La classe XmlReader usa le regole definite dalla raccomandazione W3C XML Schema Part 2: Datatypes.
| Utilizzare questo metodo XmlReader | Per restituire il 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 parametro returnType |
| ReadContentAsObject e ReadElementContentAsObject | Tipo più appropriato, come specificato dalla proprietà XmlReader.ValueType. Per informazioni sul mapping, consultare il supporto di tipo 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 tipo xs:date e quindi viene utilizzato il metodo ReadElementContentAsDateTime per restituire l'elemento come oggetto DateTime.
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: {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 metodi XmlReader ha controparti asincrone con "Async" alla fine dei nomi dei metodi. Ad esempio, l'equivalente asincrono di ReadContentAsObject è ReadContentAsObjectAsync.
I metodi seguenti possono essere usati con chiamate di metodi asincrone.
- GetAttribute
- MoveToAttribute
- MoveToFirstAttribute
- MoveToNextAttribute
- MoveToElement
- ReadAttributeValue
- ReadSubtree
- ResolveEntity
Le sezioni seguenti descrivono l'utilizzo asincrono per i metodi che non dispongono di controparti asincrone.
metodo 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
metodo 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
Metodo 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
metodo 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
metodo 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
Considerazioni sulla sicurezza
Quando si lavora con la classe XmlReader, tenere presente quanto segue:
Le eccezioni generate dal XmlReader possono divulgare informazioni sul percorso che potresti non voler esporre all'interno della tua applicazione. L'app deve intercettare le eccezioni ed elaborarle in modo appropriato.
Non abilitare l'elaborazione DTD se si è preoccupati riguardo a problemi di negazione del servizio o se si gestiscono fonti non attendibili. L'elaborazione DTD è disabilitata per impostazione predefinita per gli oggetti XmlReader creati dal metodo Create.
Se è abilitata l'elaborazione DTD, è possibile usare il XmlSecureResolver per limitare le risorse a cui l'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.
I dati XML possono includere riferimenti a risorse esterne, ad esempio un file di schema. Per impostazione predefinita, le risorse esterne vengono risolte usando un oggetto XmlUrlResolver senza credenziali utente. È possibile proteggere ulteriormente questa operazione eseguendo una delle operazioni seguenti:
Limitare le risorse a cui l'XmlReader può accedere impostando la proprietà XmlReaderSettings.XmlResolver su un oggetto XmlSecureResolver.
Non consentire all'XmlReader di aprire risorse esterne impostando la proprietà XmlReaderSettings.XmlResolver su
null.
I flag di convalida ProcessInlineSchema e ProcessSchemaLocation di un oggetto XmlReaderSettings non sono impostati per impostazione predefinita. Ciò consente di proteggere la XmlReader dagli attacchi basati sullo schema quando elabora dati XML da un'origine non attendibile. Quando questi flag vengono impostati, la XmlResolver dell'oggetto XmlReaderSettings viene utilizzata per risolvere le posizioni degli schemi rilevate nel documento dell'istanza nel XmlReader. Se la proprietà XmlResolver è impostata su
null, i percorsi dello schema non vengono risolti anche se vengono impostati i flag di convalida ProcessInlineSchema e ProcessSchemaLocation.Gli schemi aggiunti durante la convalida aggiungono nuovi tipi e possono modificare il risultato della convalida del documento da convalidare. Di conseguenza, gli schemi esterni devono essere risolti solo da origini attendibili.
È consigliabile disabilitare il flag ProcessIdentityConstraints durante la convalida di 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, dichiarazioni dello spazio dei nomi, elementi annidati e così via che richiedono una notevole quantità di tempo per l'elaborazione. Per limitare le dimensioni dell'input inviato al XmlReader, è possibile:
Limitare le dimensioni del documento impostando la proprietà MaxCharactersInDocument.
Limitare il numero di caratteri risultanti dall'espansione delle entità impostando la proprietà MaxCharactersFromEntities.
Creare un'implementazione di
IStreampersonalizzata per l'XmlReader.
Il metodo ReadValueChunk può essere usato per gestire flussi di dati di grandi dimensioni. Questo metodo legge un numero ridotto di caratteri alla volta anziché 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 proprietà LocalName, Prefixo NamespaceURI per ogni elemento, la stringa restituita viene aggiunta a un NameTable. La raccolta contenuta nella NameTable non diminuisce mai di dimensioni, creando una perdita di memoria virtuale degli handle di stringa. Una mitigazione di questo tipo consiste nel derivare dalla classe NameTable e applicare una quota di dimensioni massime. Non è possibile impedire l'uso di un NameTableo di cambiare il NameTable quando è pieno. Un'altra mitigazione consiste nell'evitare di usare le proprietà indicate e usare invece il metodo MoveToAttribute con il metodo IsStartElement ove possibile; questi metodi non restituiscono stringhe e quindi evitano il problema di sovraccaricare la raccolta NameTable.
XmlReaderSettings oggetti possono contenere informazioni riservate, ad esempio credenziali utente. Un componente non attendibile può usare l'oggetto XmlReaderSettings e le relative credenziali utente per creare oggetti XmlReader per leggere i dati. Prestare attenzione quando si memorizzano nella cache XmlReaderSettings oggetti o quando si passa l'oggetto XmlReaderSettings da un componente a un altro.
Non accettare componenti di supporto, ad esempio NameTable, XmlNamespaceManagere oggetti XmlResolver, da un'origine non attendibile.