Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.
XmlReader poskytuje přístup k datům XML v dokumentu nebo datovém proudu jen pro čtení a jen pro postup vpřed. Tato třída odpovídá doporučením W3C Extensible Markup Language (XML) 1.0 (čtvrtá edice) a jmenným prostorům v XML 1.0 (třetí edice).
XmlReader metody umožňují procházet data XML a číst obsah uzlu. Vlastnosti třídy odrážejí hodnotu aktuálního uzlu, kde je čtenář umístěn. Hodnota ReadState vlastnosti označuje aktuální stav čtečky XML. Například vlastnost je nastavena ReadState.Initial metodou XmlReader.Read a ReadState.Closed metodou XmlReader.Close . XmlReader poskytuje také kontroly a ověřování shody dat s DTD nebo schématem.
XmlReader používá vytahovací model k načtení dat. Tento model:
- Zjednodušuje správu stavu přirozeným procedurálním upřesněním shora dolů.
- Podporuje více vstupních datových proudů a vrstvení.
- Umožňuje klientovi dát analyzátoru vyrovnávací paměť, do které je řetězec přímo zapsán, a tím se vyhnout nutnosti dodatečné kopie řetězce.
- Podporuje selektivní zpracování. Klient může přeskočit položky a zpracovat ty, které jsou pro aplikaci zajímavé. Můžete také nastavit vlastnosti předem a spravovat způsob zpracování datového proudu XML (například normalizace).
Vytvoření čtečky XML
Použijte metodu CreateXmlReader k vytvoření instance.
I když .NET poskytuje konkrétní implementace XmlReader třídy, například XmlTextReader, XmlNodeReadera XmlValidatingReader třídy, doporučujeme používat specializované třídy pouze v těchto scénářích:
- Pokud chcete číst podstrom XML DOM z objektu XmlNode , použijte XmlNodeReader třídu. (Tato třída ale nepodporuje ověřování DTD ani schématu.)
- Pokud je nutné rozšířit entity na vyžádání, nechcete, aby byl textový obsah normalizován nebo nechcete, aby se vrátily výchozí atributy, použijte XmlTextReader třídu.
Chcete-li zadat sadu funkcí, které chcete povolit pro čtečku XML, předejte System.Xml.XmlReaderSettings objekt metodě Create . Jeden System.Xml.XmlReaderSettings objekt můžete použít k vytvoření více čtenářů se stejnou funkcí nebo úpravou objektu System.Xml.XmlReaderSettings a vytvořit novou čtečku s jinou sadou funkcí. Do existujícího čtenáře můžete také snadno přidávat funkce.
Pokud nepoužíváte objekt System.Xml.XmlReaderSettings, použijí se výchozí nastavení. Podrobnosti najdete na Create referenční stránce.
XmlReader vyvolá XmlException při chybách analýzy XML. Po vyvolání výjimky není stav čtenáře předvídatelný. Například hlášený typ uzlu se může lišit od skutečného typu uzlu aktuálního uzlu. ReadState Pomocí vlastnosti zkontrolujte, jestli je čtenář v chybovém stavu.
Ověření dat XML
Chcete-li definovat strukturu dokumentu XML a jeho relací prvků, datových typů a omezení obsahu, použijete schéma definice typu dokumentu (DTD) nebo XSD (XML Schema Definition Language). Dokument XML je považován za dobře vytvořený, pokud splňuje všechny syntaktické požadavky definované doporučením W3C XML 1.0. Je považována za platnou, pokud je správně vytvořená a také odpovídá omezením definovaným jeho DTD nebo schématem. (Viz schéma XML W3C část 1: Struktury a schéma XML W3C část 2: Doporučení datových typů .) Proto i když jsou všechny platné dokumenty XML dobře formátovány, nejsou všechny dobře formátované dokumenty XML platné.
Data můžete ověřit pomocí DTD, vloženého schématu XSD nebo schématu XSD uloženého XmlSchemaSet v objektu (mezipaměti). Tyto scénáře jsou popsány na Create referenční stránce. XmlReader nepodporuje XML-Data omezené ověřování schématu (XDR).
Následující nastavení třídy XmlReaderSettings slouží k určení typu ověření, pokud existuje, XmlReader instance podporuje.
| Použijte tohoto XmlReaderSettings člena | Upřesnit |
|---|---|
| DtdProcessing vlastnost | Určuje, jestli se má povolit zpracování DTD. Výchozí hodnota je zakázat zpracování DTD. |
| ValidationType vlastnost | Určuje, jestli má čtenář ověřovat data a jaký typ ověření má provést (DTD nebo schéma). Výchozí stav je bez ověření dat. |
| událost ValidationEventHandler | Obslužná rutina události pro příjem informací o událostech ověření. Pokud není zadána obslužná rutina události, při první chybě ověření se vyvolá XmlException. |
| ValidationFlags vlastnost | Další možnosti ověřování prostřednictvím členů výčtu XmlSchemaValidationFlags : - AllowXmlAttributes-- Povolí atributy XML (xml:*) v dokumentech instancí, i když nejsou definovány ve schématu. Atributy se ověřují na základě jejich datového typu.
XmlSchemaValidationFlags Na stránce s referenčními informacemi najdete nastavení, které se má použít v konkrétních scénářích. (Ve výchozím nastavení je zakázáno.)- ProcessIdentityConstraints --Procesní omezení identity (xs:ID, xs:IDREF, xs:key, xs:keyref, xs:unique) zjištěna během ověřování. (Ve výchozím nastavení povoleno.)- ProcessSchemaLocation--Zpracovat schémata určená atributem xsi:schemaLocation nebo atributem xsi:noNamespaceSchemaLocation. (Ve výchozím nastavení povoleno.)- ProcessInlineSchema-- Zpracování vložených schémat XML během ověřování. (Ve výchozím nastavení je zakázáno.)- ReportValidationWarnings--Nahlaste události, pokud dojde k varování při ověření. Upozornění se obvykle vydává, pokud neexistuje žádné schéma DTD nebo XML k ověření konkrétního elementu nebo atributu.
ValidationEventHandler je použito pro oznámení. (Ve výchozím nastavení je zakázáno.) |
| Schemas | XmlSchemaSet k použití pro ověření. |
| XmlResolver vlastnost | Řešení XmlResolver a přístup k externím prostředkům. To může zahrnovat externí entity, jako jsou DTD a schémata, a všechny xs:include nebo xs:import prvky obsažené ve schématu XML. Pokud nezadáte XmlResolver, XmlReader se použije výchozí XmlUrlResolver bez uživatelských údajů. |
Shoda s daty
Čtečky XML vytvořené metodou Create splňují následující požadavky na dodržování předpisů ve výchozím nastavení:
Nové řádky a hodnota atributu jsou normalizovány podle doporučení W3C XML 1.0.
Všechny entity se automaticky rozbalí.
Výchozí atributy deklarované v definici typu dokumentu se vždy přidají i v případě, že čtenář neověří.
Deklarace předpony XML namapované na správný identifikátor URI oboru názvů XML je povolena.
Názvy notací v deklaraci jednoho
NotationTypeatributu aNmTokensv deklaraci jednohoEnumerationatributu jsou odlišné.
Pomocí těchto XmlReaderSettings vlastností určete typ kontrol shody, které chcete povolit:
| Použít tuto XmlReaderSettings vlastnost | Do | Výchozí |
|---|---|---|
| CheckCharacters vlastnost | Povolte nebo zakažte kontroly následujících: - Znaky jsou v rozsahu právních znaků XML, jak je definováno oddílem 2,2 Znaků v doporučení W3C XML 1.0. - Všechny názvy XML jsou platné, jak je definováno oddílem 2.3 Společné syntaktické konstruktory v doporučení W3C XML 1.0. Pokud je tato vlastnost nastavena na true (výchozí), vyvolá XmlException se výjimka, pokud soubor XML obsahuje neplatné znaky nebo neplatné názvy XML (například název elementu začíná číslem). |
Kontrola znaků a názvů je povolena. Nastavením CheckCharacters na false se vypne kontrola znaků u odkazů na znakové entity. Pokud čtečka zpracovává textová data, vždy zkontroluje platnost názvů XML bez ohledu na toto nastavení.
Poznámka: Doporučení XML 1.0 vyžaduje shodu na úrovni dokumentu, pokud je k dispozici DTD. Proto pokud je čtečka nakonfigurována tak, aby podporovala ConformanceLevel.Fragment, ale data XML obsahují definici typu dokumentu (DTD), XmlException je vyvolán. |
| ConformanceLevel vlastnost | Zvolte úroveň shody, která se má vynutit: - Document. Odpovídá pravidlům pro dokument XML 1.0 ve správném formátu. - Fragment. Odpovídá pravidlům pro dobře formátovaný fragment dokumentu, který lze použít jako externí analyzovanou entitu. - Auto. Odpovídá úrovni, o které rozhoduje čtenář. Pokud data neodpovídají, vyvolá se XmlException výjimka. |
Document |
Procházet mezi uzly
Aktuální uzel je uzel XML, na kterém je aktuálně umístěna čtečka XML. Všechny XmlReader metody provádějí operace ve vztahu k tomuto uzlu a všechny XmlReader vlastnosti odrážejí hodnotu aktuálního uzlu.
Následující metody usnadňují procházení uzlů a parsování dat.
| Použít tuto XmlReaderSettings metodu | Do |
|---|---|
| Read | Přečtěte si první uzel a postupujte tokem po jednom uzlu. Taková volání se obvykle provádějí uvnitř while smyčky.NodeType Pomocí vlastnosti získejte typ (například atribut, komentář, element atd.) aktuálního uzlu. |
| Skip | Přeskočte podřízené položky aktuálního uzlu a přejděte na další uzel. |
| MoveToContent a MoveToContentAsync | Přeskočte uzly bez obsahu a přejděte na další uzel obsahu nebo na konec souboru. Mezi uzly, které nejsou obsahem, patří ProcessingInstruction, DocumentTypeComment, Whitespace, a SignificantWhitespace. Mezi uzly obsahu patří text, který není prázdný, CDATAEntityReference a EndEntity. |
| ReadSubtree | Přečtěte si prvek a všechny jeho podřízené položky a vraťte novou XmlReader instanci nastavenou na ReadState.Initial. Tato metoda je užitečná pro vytváření hranic kolem elementů XML; Pokud například chcete předat data jiné komponentě ke zpracování a chcete omezit, kolik dat má komponenta přístup. |
Podívejte se na XmlReader.Read referenční stránku, kde najdete příklad procházení textového streamu po jednom uzlu a zobrazení typu každého uzlu.
Následující části popisují, jak můžete číst konkrétní typy dat, jako jsou prvky, atributy a typová data.
Čtení elementů XML
Následující tabulka uvádí metody a vlastnosti, které XmlReader třída poskytuje pro zpracování prvků. XmlReader Po umístění prvku vlastnosti uzlu, například Name, odrážejí hodnoty elementu. Kromě níže popsaných členů lze k zpracování prvků použít také některou z obecných metod a vlastností XmlReader třídy. Můžete například použít metodu ReadInnerXml ke čtení obsahu elementu.
Poznámka:
Viz část 3.1 doporučení XML W3C 1.0 pro definice počátečních značek, koncových značek a prázdných značek elementů.
| Použijte tohoto XmlReader člena | Do |
|---|---|
| metoda IsStartElement | Zkontrolujte, jestli je aktuální uzel počáteční značkou nebo prázdnou značkou elementu. |
| metoda ReadStartElement | Zkontrolujte, jestli je aktuální uzel prvkem, a posuňte ukazatel na další uzel (volání IsStartElement následované Read). |
| metoda ReadEndElement | Zkontrolujte, zda je aktuální uzel koncovou značkou, a posuňte čtečku na další uzel. |
| metoda ReadElementString | Přečtěte si textový prvek |
| metoda ReadToDescendant | Posuňte XML čtečku k následujícímu podřízenému elementu, který má zadaný název. |
| metoda ReadToNextSibling | Posuňte čtečku XML k dalšímu sourozeneckému prvku, který má zadaný název. |
| IsEmptyElement vlastnost | Zkontrolujte, jestli má aktuální prvek značku koncového prvku. Například: - <item num="123"/> (IsEmptyElement je true.)- <item num="123"> </item> (IsEmptyElement je false, i když obsah prvku je prázdný.) |
Příklad čtení textového obsahu prvků naleznete v ReadString metodě. Následující příklad zpracovává prvky pomocí smyčky 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
Čtení atributů XML
Atributy XML se nejčastěji vyskytují u elementů, ale jsou také povoleny u deklarací XML a uzlů typu dokumentu.
Při umístění na uzlu elementu MoveToAttribute umožňuje metoda projít seznam atributů elementu. Všimněte si, že po zavolání MoveToAttribute vlastnosti uzlu, jako jsou Name, NamespaceURI a Prefix, odrážejí vlastnosti tohoto atributu, ale nikoli vlastnosti prvku, ke kterému atribut patří.
Třída XmlReader poskytuje tyto metody a vlastnosti pro čtení a zpracování atributů prvků.
| Použijte tohoto XmlReader člena | Do |
|---|---|
| HasAttributes vlastnost | Zkontrolujte, jestli má aktuální uzel nějaké atributy. |
| AttributeCount vlastnost | Získejte počet atributů pro aktuální prvek. |
| metoda MoveToFirstAttribute | Přechod na první atribut v elementu |
| metoda MoveToNextAttribute | Přechod na další atribut v elementu |
| metoda MoveToAttribute | Přechod na zadaný atribut |
| GetAttribute metoda nebo Item[] vlastnost | Získá hodnotu zadaného atributu. |
| IsDefault vlastnost | Zkontrolujte, jestli je aktuální uzel atributem vygenerovaným z výchozí hodnoty definované v DTD nebo schématu. |
| metoda MoveToElement | Přechod na prvek, který vlastní aktuální atribut. Tuto metodu použijte k návratu k prvku po procházení jeho atributů. |
| metoda ReadAttributeValue | Parsuj hodnotu atributu do jednoho nebo více uzlů Text, EntityReference, nebo EndEntity. |
Všechny obecné XmlReader metody a vlastnosti lze také použít ke zpracování atributů. Například, když je XmlReader umístěn na atributu, vlastnosti Name a Value odrážejí hodnoty tohoto atributu. K získání hodnoty atributu můžete použít také některou z metod obsahu Read .
Tento příklad používá AttributeCount vlastnost k procházení všech atributů v elementu.
// 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
Tento příklad používá metodu MoveToNextAttribute v cyklu while k procházení atributů.
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
Čtení atributů v uzlech deklarace XML
Když je čtečka XML umístěna na uzlu deklarace XML, vlastnost Value vrátí informace o verzi, samostatnosti a kódování jako jeden řetězec. XmlReader objekty vytvořené metodou Create, třídou XmlTextReader a třídou XmlValidatingReader zpřístupňují položky verze, nezávislosti a kódování jako atributy.
Čtení atributů na uzlech typu dokumentu
Pokud je čtečka XML umístěna na uzlu typu dokumentu, lze metodu GetAttribute a Item[] vlastnost použít k vrácení hodnot pro SYSTÉM a VEŘEJNÉ literály. Volání například reader.GetAttribute("PUBLIC") vrátí hodnotu PUBLIC.
Čtení atributů při zpracování uzlů instrukcí
Když je XmlReader umístěn na uzel zpracování instrukce, Value vlastnost vrátí celý textový obsah. Položky v uzlu instrukce zpracování nejsou považovány za atributy. Nelze je přečíst pomocí GetAttribute metody ani MoveToAttribute metody.
Čtení obsahu XML
XmlReader třída obsahuje následující členy, které čtou obsah ze souboru XML a vrací obsah jako řetězcové hodnoty. (Chcete-li vrátit typy CLR, přečtěte si téma Převod na typy CLR.)
| Použijte tohoto XmlReader člena | Do |
|---|---|
| Value vlastnost | Získá textový obsah aktuálního uzlu. Vrácená hodnota závisí na typu uzlu; Podrobnosti najdete na Value stránce s referenčními informacemi. |
| metoda ReadString | Získá obsah prvku nebo textového uzlu jako řetězec. Tato metoda zastaví zpracování pokynů a komentářů. Podrobnosti o tom, jak tato metoda zpracovává konkrétní typy uzlů, najdete na ReadString referenční stránce. |
| metody ReadInnerXml a ReadInnerXmlAsync | Získejte veškerý obsah aktuálního uzlu, včetně značkování, kromě počátečních a koncových tagů. Například pro:<node>this<child id="123"/></node>ReadInnerXml výstupy: this<child id="123"/> |
| metody ReadOuterXml a ReadOuterXmlAsync | Získejte veškerý obsah aktuálního uzlu a jeho podřízených uzlů, včetně značek a začínajících/koncových tagů. Například pro:<node>this<child id="123"/></node>ReadOuterXml výstupy: <node>this<child id="123"/></node> |
Převod na typy CLR
Členy XmlReader třídy (uvedené v následující tabulce) můžete použít ke čtení dat XML a vrácení hodnot jako typů CLR (Common Language Runtime) místo řetězců. Tito členové umožňují získat hodnoty v reprezentaci, která je nejvhodnější pro úkol kódování, aniž byste museli ručně parsovat nebo převést řetězcové hodnoty.
Metody ReadElementContentAs lze volat pouze u typů uzlů elementů. Tyto metody nelze použít na prvcích, které obsahují podřízené prvky nebo smíšený obsah. Při zavolání XmlReader objekt přečte počáteční značku, přečte obsah elementu a pak se přesune za značku koncového prvku. Pokyny ke zpracování a komentáře se ignorují a entity se rozšiřují.
Metody ReadContentAs čtou textový obsah v aktuální pozici čtenáře a pokud data XML nemají přidružené žádné schéma nebo informace o datovém typu, převeďte textový obsah na požadovaný návratový typ. Text, prázdné znaky, významné prázdné znaky a sekce CDATA jsou zřetězeny. Komentáře a pokyny ke zpracování se přeskočí a odkazy na entity se automaticky vyřeší.
Třída XmlReader používá pravidla definovaná schématem XML W3C část 2: Doporučení datových typů .
| Použít tuto XmlReader metodu | Vrátit tento typ CLR |
|---|---|
| ReadContentAsBoolean a ReadElementContentAsBoolean | Boolean |
| ReadContentAsDateTime a ReadElementContentAsDateTime | DateTime |
| ReadContentAsDouble a ReadElementContentAsDouble | Double |
| ReadContentAsLong a ReadElementContentAsLong | Int64 |
| ReadContentAsInt a ReadElementContentAsInt | Int32 |
| ReadContentAsString a ReadElementContentAsString | String |
| ReadContentAs a ReadElementContentAs | Typ, který zadáte pomocí parametru returnType |
| ReadContentAsObject a ReadElementContentAsObject | Nejvhodnější typ, jak je určeno vlastností XmlReader.ValueType . Informace o mapování naleznete v části Podpora typů v třídách System.Xml . |
Pokud prvek nelze snadno převést na typ CLR z důvodu jeho formátu, můžete použít mapování schématu k zajištění úspěšného převodu. Následující příklad používá soubor .xsd k převodu hire-date elementu na xs:date typ a pak používá metodu ReadElementContentAsDateTime k vrácení elementu DateTime jako objektu.
Vstup (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>
Kód:
// 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
Výstup:
Six Month Review Date: 7/8/2003 12:00:00 AM
Asynchronní programování
XmlReader Většina metod má asynchronní protějšky, které mají na konci názvů metod "Async". Například asynchronní ekvivalent ReadContentAsObject je ReadContentAsObjectAsync.
Následující metody lze použít s asynchronními voláními metod:
- GetAttribute
- MoveToAttribute
- MoveToFirstAttribute
- MoveToNextAttribute
- MoveToElement
- ReadAttributeValue
- ReadSubtree
- ResolveEntity
Následující části popisují asynchronní použití metod, které nemají asynchronní protějšky.
Metoda 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
Metoda 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
Metoda 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
Metoda 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
Metoda 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
Bezpečnostní aspekty
Při práci s XmlReader třídou zvažte následující skutečnosti:
Výjimky vyvolané z XmlReader můžou odhalit informace o cestě, které nechcete, aby byly předány do vaší aplikace. Vaše aplikace musí zachytit výjimky a odpovídajícím způsobem je zpracovat.
Nepovolujte zpracování DTD, pokud máte obavy o problémy s odepřením služeb nebo pokud pracujete s nedůvěryhodnými zdroji. Zpracování DTD je ve výchozím nastavení zakázané pro XmlReader objekty vytvořené metodou Create .
Pokud máte povolené zpracování DTD, můžete použít XmlSecureResolver omezení prostředků, ke kterým XmlReader má přístup. Aplikaci můžete také navrhnout tak, aby zpracování XML bylo omezené na paměť a čas. V aplikaci ASP.NET můžete například nakonfigurovat časové limity.
Data XML můžou obsahovat odkazy na externí prostředky, jako je soubor schématu. Ve výchozím nastavení se externí prostředky řeší pomocí objektu XmlUrlResolver bez přihlašovacích údajů uživatele. Můžete to dále zabezpečit jedním z následujících způsobů:
Omezte prostředky, ke kterým XmlReader má přístup, nastavením XmlReaderSettings.XmlResolver vlastnosti na XmlSecureResolver objekt.
Nepovolte XmlReader otevření žádných externích prostředků nastavením XmlReaderSettings.XmlResolver vlastnosti na
null.
Příznaky ověřování objektu ProcessInlineSchema a ProcessSchemaLocation nejsou ve výchozím nastavení aktivovány. To pomáhá chránit XmlReader před útoky založenými na schématu při zpracování dat XML z nedůvěryhodného zdroje. Když jsou tyto příznaky nastaveny, XmlResolver objektu XmlReaderSettings je použit k určení umístění schémat nalezených v dokumentu instance v XmlReader. Pokud je vlastnost XmlResolver nastavená na
null, umístění schématu se nevyřeší, i když jsou nastavené příznaky ověřování ProcessInlineSchema a ProcessSchemaLocation.Schémata přidaná během ověřování přidávají nové typy a můžou změnit výsledek ověření ověřovaného dokumentu. V důsledku toho by externí schémata měla být vyřešena pouze z důvěryhodných zdrojů.
Doporučujeme zakázat příznak ProcessIdentityConstraints při ověřování velkých a nedůvěryhodných XML dokumentů ve scénářích s vysokou dostupností podle schématu, které má omezení identity nad velkou částí dokumentu. Tento příznak je ve výchozím nastavení povolený.
Data XML můžou obsahovat velký počet atributů, deklarací oboru názvů, vnořených elementů atd., které vyžadují značné množství času ke zpracování. Chcete-li omezit velikost vstupu odeslaného do XmlReader, můžete:
Omezte velikost dokumentu nastavením MaxCharactersInDocument vlastnosti.
Omezte počet znaků, které jsou výsledkem rozbalení entit, nastavením vlastnosti MaxCharactersFromEntities.
Vytvořte vlastní
IStreamimplementaci pro XmlReader.
Metodu ReadValueChunk lze použít ke zpracování velkých datových proudů. Tato metoda čte malý počet znaků v jeden okamžik místo přidělení jednoho řetězce pro kompletní hodnotu.
Při čtení dokumentu XML s velkým počtem jedinečných místních názvů, oborů názvů nebo předpon může dojít k problému. Pokud používáte třídu, která je odvozena od XmlReader, a voláte vlastnost LocalName, Prefix nebo NamespaceURI pro každou položku, vrácený řetězec je přidán do NameTable. Kolekce uchovávaná NameTable nikdy nezmenšuje svou velikost, což vytváří virtuální únik paměti u popisovačů řetězců. Jedním ze způsobů snížení rizika je odvození třídy NameTable a vynucení maximální velikosti. (Neexistuje způsob, jak zabránit použití NameTable, nebo přepnout NameTable, když je plný). Dalším zmírněním rizik je vyhnout se použití uvedených vlastností a místo toho použít MoveToAttribute metodu s metodou IsStartElement , pokud je to možné; tyto metody nevrací řetězce, a proto se vyhnete problému přeplnění NameTable kolekce.
XmlReaderSettings objekty mohou obsahovat citlivé informace, jako jsou přihlašovací údaje uživatele. Nedůvěryhodná komponenta může objekt a jeho přihlašovací údaje uživatele použít XmlReaderSettings k vytvoření XmlReader objektů pro čtení dat. Při ukládání objektů do mezipaměti XmlReaderSettings nebo při předávání objektu XmlReaderSettings z jedné komponenty do jiné buďte opatrní.
Nepřijímejte podpůrné komponenty, jako jsou objekty NameTable, XmlNamespaceManager a XmlResolver z nedůvěryhodného zdroje.