System.Xml.XmlReader, klasa
Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.
XmlReader zapewnia dostęp tylko do odczytu do danych XML w dokumencie lub strumieniu. Ta klasa jest zgodna z zaleceniami języka W3C Extensible Markup Language (XML) 1.0 (czwarta wersja) i przestrzeniami nazw w języku XML 1.0 (trzecia wersja).
XmlReader metody umożliwiają przechodzenie przez dane XML i odczytywanie zawartości węzła. Właściwości klasy odzwierciedlają wartość bieżącego węzła, czyli miejsce, w którym znajduje się czytnik. Wartość ReadState właściwości wskazuje bieżący stan czytnika XML. Na przykład właściwość jest ustawiana na ReadState.Initial wartość przy użyciu XmlReader.Read metody i ReadState.Closed metody XmlReader.Close . XmlReader Zapewnia również sprawdzanie zgodności danych i walidację względem dtD lub schematu.
XmlReader używa modelu ściągania do pobierania danych. Ten model:
- Upraszcza zarządzanie stanem przez naturalne, odgórne uściślenie proceduralne.
- Obsługuje wiele strumieni wejściowych i warstw.
- Umożliwia klientowi nadanie analizatorowi buforu, w którym ciąg jest zapisywany bezpośrednio, a tym samym unika konieczności dodatkowej kopii ciągu.
- Obsługuje przetwarzanie selektywne. Klient może pominąć elementy i przetworzyć te, które są interesujące dla aplikacji. Można również ustawić właściwości z wyprzedzeniem, aby zarządzać sposobem przetwarzania strumienia XML (na przykład normalizacji).
Tworzenie czytnika XML
Create Użyj metody , aby utworzyć XmlReader wystąpienie.
Mimo że platforma .NET udostępnia konkretne implementacje XmlReader klasy, takie jak XmlTextReader, XmlNodeReaderi , i XmlValidatingReader , zalecamy używanie wyspecjalizowanych klas tylko w następujących scenariuszach:
- Jeśli chcesz odczytać poddrzewo DOM XML z XmlNode obiektu, użyj XmlNodeReader klasy . (Jednak ta klasa nie obsługuje walidacji dtD ani schematu).
- Jeśli musisz rozwinąć jednostki na żądanie, nie chcesz, aby zawartość tekstowa została znormalizowana lub nie chcesz zwracać atrybutów domyślnych, użyj XmlTextReader klasy .
Aby określić zestaw funkcji, które chcesz włączyć w czytniku XML, przekaż System.Xml.XmlReaderSettings obiekt do Create metody . Można użyć pojedynczego System.Xml.XmlReaderSettings obiektu do utworzenia wielu czytników z tą samą funkcjonalnością lub zmodyfikować System.Xml.XmlReaderSettings obiekt w celu utworzenia nowego czytnika z innym zestawem funkcji. Możesz również łatwo dodawać funkcje do istniejącego czytnika.
Jeśli nie używasz System.Xml.XmlReaderSettings obiektu, są używane ustawienia domyślne. Aby uzyskać szczegółowe informacje, zobacz stronę referencyjną Create .
XmlReader zgłasza błędy XmlException analizy XML. Po wystąpieniu wyjątku stan czytnika nie jest przewidywalny. Na przykład zgłoszony typ węzła może różnić się od rzeczywistego typu węzła bieżącego węzła. Użyj właściwości , ReadState aby sprawdzić, czy czytnik jest w stanie błędu.
Weryfikowanie danych XML
Aby zdefiniować strukturę dokumentu XML i jego relacji elementów, typów danych i ograniczeń zawartości, należy użyć schematu definicji typu dokumentu (DTD) lub języka definicji schematu XML (XSD). Dokument XML jest uznawany za dobrze sformułowany, jeśli spełnia wszystkie wymagania składniowe zdefiniowane przez zalecenie W3C XML 1.0. Jest on uznawany za prawidłowy, jeśli jest dobrze sformułowany, a także jest zgodny z ograniczeniami zdefiniowanymi przez jego dtD lub schemat. (Zobacz Schemat XML W3C — część 1: struktury i schemat XML W3C — część 2: zalecenia dotyczące typów danych). W związku z tym, mimo że wszystkie prawidłowe dokumenty XML są dobrze sformułowane, nie wszystkie poprawnie sformułowane dokumenty XML są prawidłowe.
Możesz zweryfikować dane względem dtD, wbudowanego schematu XSD lub schematu XSD przechowywanego XmlSchemaSet w obiekcie (pamięci podręcznej). Te scenariusze są opisane na stronie referencyjnej Create . XmlReader nie obsługuje weryfikacji schematu XML-Data Reduced (XDR).
W klasie są używane następujące ustawienia XmlReaderSettings , aby określić typ weryfikacji, jeśli istnieje, XmlReader wystąpienie obsługuje.
Użyj tego XmlReaderSettings elementu członkowskiego | Aby określić |
---|---|
DtdProcessing Właściwość | Czy zezwolić na przetwarzanie DTD. Wartością domyślną jest nie zezwalanie na przetwarzanie DTD. |
ValidationType Właściwość | Czy czytelnik powinien zweryfikować dane, oraz jakiego typu walidację należy wykonać (DTD lub schemat). Wartość domyślna to brak walidacji danych. |
ValidationEventHandler Zdarzenie | Procedura obsługi zdarzeń służąca do odbierania informacji o zdarzeniach weryfikacji. Jeśli program obsługi zdarzeń nie zostanie podany, XmlException zostanie zgłoszony pierwszy błąd weryfikacji. |
ValidationFlags Właściwość | Dodatkowe opcje walidacji za pośrednictwem elementów XmlSchemaValidationFlags członkowskich wyliczenia: - AllowXmlAttributes -- Zezwalaj na atrybuty XML (xml:* ) w dokumentach wystąpień nawet wtedy, gdy nie są zdefiniowane w schemacie. Atrybuty są weryfikowane na podstawie ich typu danych. Zobacz stronę referencyjną XmlSchemaValidationFlags ustawienia do użycia w określonych scenariuszach. (Domyślnie wyłączone).- ProcessIdentityConstraints --Przetwarzanie ograniczeń tożsamości (xs:ID , xs:IDREF , xs:key , xs:keyref , xs:unique ) napotkanych podczas walidacji. (Domyślnie włączone).- ProcessSchemaLocation --Przetwarzanie schematów określonych przez xsi:schemaLocation atrybut or xsi:noNamespaceSchemaLocation . (Domyślnie włączone).- ProcessInlineSchema -- Przetwarzanie wbudowanych schematów XML podczas walidacji. (Domyślnie wyłączone).- ReportValidationWarnings --Zgłaszaj zdarzenia, jeśli wystąpi ostrzeżenie o walidacji. Ostrzeżenie jest zwykle wystawiane, gdy nie ma identyfikatora DTD lub schematu XML w celu zweryfikowania określonego elementu lub atrybutu. Element ValidationEventHandler jest używany do powiadamiania. (Domyślnie wyłączone). |
Schemas | Element XmlSchemaSet do użycia do weryfikacji. |
XmlResolver Właściwość | Element XmlResolver do rozpoznawania i uzyskiwania dostępu do zasobów zewnętrznych. Może to obejmować jednostki zewnętrzne, takie jak DTD i schematy, oraz wszystkie xs:include elementy lub xs:import zawarte w schemacie XML. Jeśli nie określisz XmlResolverwartości , XmlReader zostanie użyta wartość domyślna XmlUrlResolver bez poświadczeń użytkownika. |
Zgodność danych
Czytniki XML tworzone przez metodę Create domyślnie spełniają następujące wymagania dotyczące zgodności:
Nowe wiersze i wartość atrybutu są znormalizowane zgodnie z zaleceniem W3C XML 1.0.
Wszystkie jednostki są automatycznie rozwinięte.
Atrybuty domyślne zadeklarowane w definicji typu dokumentu są zawsze dodawane nawet wtedy, gdy czytelnik nie sprawdza poprawności.
Deklaracja prefiksu XML zamapowanego na prawidłowy identyfikator URI przestrzeni nazw XML jest dozwolona.
Nazwy notacji w pojedynczej
NotationType
deklaracji atrybutu iNmTokens
w jednejEnumeration
deklaracji atrybutu są odrębne.
Użyj tych XmlReaderSettings właściwości, aby określić typ kontroli zgodności, które chcesz włączyć:
Użyj tej XmlReaderSettings właściwości | To | Wartość domyślna |
---|---|---|
CheckCharacters Właściwość | Włącz lub wyłącz kontrole dla następujących elementów: - Znaki znajdują się w zakresie znaków prawnych XML, zgodnie z definicją w sekcji 2.2 Znaki zalecenia W3C XML 1.0. — Wszystkie nazwy XML są prawidłowe, zgodnie z definicją w sekcji Typowe konstrukcje składniowe 2.3 zalecenia W3C XML 1.0. Gdy ta właściwość jest ustawiona na true (wartość domyślna), zgłaszany jest wyjątek, XmlException jeśli plik XML zawiera niedozwolone znaki lub nieprawidłowe nazwy XML (na przykład nazwa elementu zaczyna się od liczby). |
Sprawdzanie znaków i nazw jest włączone. Ustawienie CheckCharacters powoduje false wyłączenie sprawdzania znaków dla odwołań do jednostki znaków. Jeśli czytelnik przetwarza dane tekstowe, zawsze sprawdza, czy nazwy XML są prawidłowe, niezależnie od tego ustawienia. Uwaga: zalecenie XML 1.0 wymaga zgodności na poziomie dokumentu, gdy istnieje dtD. W związku z tym, jeśli czytnik jest skonfigurowany do obsługi ConformanceLevel.Fragment, ale dane XML zawierają definicję typu dokumentu (DTD), XmlException jest zgłaszany. |
ConformanceLevel Właściwość | Wybierz poziom zgodności, aby wymusić: - Document. Jest zgodny z regułami dobrze sformułowanego dokumentu XML 1.0. - Fragment. Jest zgodna z regułami fragmentu dobrze sformułowanego dokumentu, który może być używany jako zewnętrzna jednostka analizowana. - Auto. Jest zgodny z poziomem określonym przez czytelnika. Jeśli dane nie są zgodne, XmlException zgłaszany jest wyjątek. |
Document |
Nawigowanie po węzłach
Bieżący węzeł to węzeł XML, w którym obecnie znajduje się czytnik XML. Wszystkie XmlReader metody wykonują operacje w odniesieniu do tego węzła, a wszystkie XmlReader właściwości odzwierciedlają wartość bieżącego węzła.
Poniższe metody ułatwiają nawigowanie po węzłach i analizowanie danych.
Użyj tej XmlReaderSettings metody | To |
---|---|
Read | Odczytywanie pierwszego węzła i przechodzenie przez strumień po jednym węźle jednocześnie. Takie wywołania są zwykle wykonywane wewnątrz while pętli.NodeType Użyj właściwości , aby uzyskać typ (na przykład atrybut, komentarz, element itd.) bieżącego węzła. |
Skip | Pomiń elementy podrzędne bieżącego węzła i przejdź do następnego węzła. |
MoveToContent i MoveToContentAsync | Pomiń węzły inne niż zawartość i przejdź do następnego węzła zawartości lub na końcu pliku. Węzły niezwiązane z zawartością obejmują ProcessingInstruction: , DocumentType, Comment, Whitespacei SignificantWhitespace. Węzły zawartości zawierają tekst inny niż biały, CDATA, EntityReference i EndEntity. |
ReadSubtree | Odczytaj element i wszystkie jego elementy podrzędne i zwróć nowe XmlReader wystąpienie ustawione na ReadState.Initialwartość . Ta metoda jest przydatna do tworzenia granic wokół elementów XML; Na przykład jeśli chcesz przekazać dane do innego składnika do przetwarzania i chcesz ograniczyć ilość danych, do których składnik może uzyskać dostęp. |
XmlReader.Read Zobacz stronę referencyjną, aby zapoznać się z przykładem nawigowania po strumieniu tekstowym po jednym węźle i wyświetlania typu każdego węzła.
W poniższych sekcjach opisano sposób odczytywania określonych typów danych, takich jak elementy, atrybuty i typizowane dane.
Odczytywanie elementów XML
W poniższej tabeli wymieniono metody i właściwości, które XmlReader udostępnia klasa do przetwarzania elementów. XmlReader Po ustawieniu elementu właściwości węzła, takie jak Name, odzwierciedlają wartości elementu. Oprócz elementów członkowskich opisanych poniżej można również używać dowolnych ogólnych metod i właściwości XmlReader klasy do przetwarzania elementów. Na przykład możesz użyć ReadInnerXml metody , aby odczytać zawartość elementu.
Uwaga
Zobacz sekcję 3.1 zalecenia W3C XML 1.0, aby zapoznać się z definicjami tagów początkowych, tagów końcowych i pustych tagów elementów.
Użyj tego XmlReader elementu członkowskiego | To |
---|---|
IsStartElement Metoda | Sprawdź, czy bieżący węzeł jest tagiem początkowym lub pustym tagiem elementu. |
ReadStartElement Metoda | Sprawdź, czy bieżący węzeł jest elementem i przejdź do następnego węzła (wywołania IsStartElement , a następnie Read). |
ReadEndElement Metoda | Sprawdź, czy bieżący węzeł jest tagiem końcowym i przejdź do następnego węzła. |
ReadElementString Metoda | Odczytywanie elementu tylko do tekstu. |
ReadToDescendant Metoda | Przejdź do następnego elementu podrzędnego (podrzędnego), który ma określoną nazwę, przejdź do czytnika XML. |
ReadToNextSibling Metoda | Przejdź do następnego elementu równorzędnego czytnika XML, który ma określoną nazwę. |
IsEmptyElement Właściwość | Sprawdź, czy bieżący element ma tag elementu końcowego. Na przykład: - <item num="123"/> (IsEmptyElement to true .)- <item num="123"> </item> (IsEmptyElement to , false chociaż zawartość elementu jest pusta). |
Aby zapoznać się z przykładem odczytywania zawartości tekstowej elementów, zobacz metodę ReadString . Poniższy przykład przetwarza elementy przy użyciu while
pętli.
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
Odczytywanie atrybutów XML
Atrybuty XML są najczęściej spotykane w elementach, ale są również dozwolone w węzłach deklaracji XML i typu dokumentu.
Po ustawieniu pozycji w węźle MoveToAttribute elementu metoda umożliwia przejście przez listę atrybutów elementu. Należy pamiętać, że po MoveToAttribute wywołaniu właściwości węzła, takie jak Name, NamespaceURIi Prefix odzwierciedlają właściwości tego atrybutu, a nie właściwości elementu, do którego należy atrybut.
Klasa XmlReader udostępnia te metody i właściwości do odczytywania i przetwarzania atrybutów elementów.
Użyj tego XmlReader elementu członkowskiego | To |
---|---|
HasAttributes Właściwość | Sprawdź, czy bieżący węzeł ma jakiekolwiek atrybuty. |
AttributeCount Właściwość | Pobierz liczbę atrybutów w bieżącym elemencie. |
MoveToFirstAttribute Metoda | Przejdź do pierwszego atrybutu w elemecie . |
MoveToNextAttribute Metoda | Przejdź do następnego atrybutu w elemecie . |
MoveToAttribute Metoda | Przejdź do określonego atrybutu. |
GetAttribute metoda lub Item[] właściwość | Pobierz wartość określonego atrybutu. |
IsDefault Właściwość | Sprawdź, czy bieżący węzeł jest atrybutem wygenerowanym na podstawie wartości domyślnej zdefiniowanej w dtD lub schemacie. |
MoveToElement Metoda | Przejdź do elementu, który jest właścicielem bieżącego atrybutu. Użyj tej metody, aby powrócić do elementu po przejściu przez jego atrybuty. |
ReadAttributeValue Metoda | Przeanalizuj wartość atrybutu w co najmniej jednym Text węźle , EntityReference lub EndEntity węzłach. |
Dowolnego z ogólnych XmlReader metod i właściwości można również używać do przetwarzania atrybutów. Na przykład po ustawieniu atrybutu XmlReader właściwości Name i Value odzwierciedlają wartości atrybutu . Możesz również użyć dowolnej metody zawartości Read
, aby uzyskać wartość atrybutu.
W tym przykładzie użyto AttributeCount właściwości do nawigowania po wszystkich atrybutach elementu.
// 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
W tym przykładzie while
użyto MoveToNextAttribute metody w pętli w celu nawigowania po atrybutach.
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
Odczytywanie atrybutów w węzłach deklaracji XML
Gdy czytnik XML jest umieszczony w węźle deklaracji XML, Value właściwość zwraca informacje o wersji, autonomicznej i kodowaniu jako pojedynczy ciąg. XmlReader obiekty utworzone przez metodę Create , XmlTextReader klasę i XmlValidatingReader klasę uwidaczniają wersję, autonomiczną i kodowanie elementów jako atrybuty.
Odczytywanie atrybutów w węzłach typu dokumentu
Gdy czytnik XML jest umieszczony w węźle typu dokumentu, GetAttribute metoda i Item[] właściwość mogą służyć do zwracania wartości literałów SYSTEM i PUBLIC. Na przykład wywołanie reader.GetAttribute("PUBLIC")
zwraca wartość PUBLIC.
Odczytywanie atrybutów przetwarzania węzłów instrukcji
Gdy właściwość XmlReader jest umieszczona w węźle instrukcji przetwarzania, Value właściwość zwraca całą zawartość tekstową. Elementy w węźle instrukcji przetwarzania nie są traktowane jako atrybuty. Nie można ich odczytać za pomocą GetAttribute metody lub MoveToAttribute .
Odczytywanie zawartości XML
Klasa XmlReader zawiera następujące elementy członkowskie, które odczytują zawartość z pliku XML i zwracają zawartość jako wartości ciągu. (Aby zwrócić typy CLR, zobacz Przekonwertuj na typy CLR).
Użyj tego XmlReader elementu członkowskiego | To |
---|---|
Value Właściwość | Pobierz zawartość tekstowa bieżącego węzła. Zwrócona wartość zależy od typu węzła; Aby uzyskać szczegółowe informacje, zobacz stronę referencyjną Value . |
ReadString Metoda | Pobierz zawartość elementu lub węzła tekstowego jako ciąg. Ta metoda zatrzymuje się na przetwarzaniu instrukcji i komentarzy. Aby uzyskać szczegółowe informacje na temat sposobu obsługi określonych typów węzłów przez tę metodę, zobacz stronę referencyjną ReadString . |
ReadInnerXml i ReadInnerXmlAsync metody | Pobierz całą zawartość bieżącego węzła, w tym znaczniki, ale z wyłączeniem tagów początkowych i końcowych. Na przykład dla:<node>this<child id="123"/></node> ReadInnerXml Zwraca: this<child id="123"/> |
ReadOuterXml i ReadOuterXmlAsync metody | Pobierz całą zawartość bieżącego węzła i jego elementów podrzędnych, w tym znaczniki i tagi początkowe/końcowe. Na przykład dla:<node>this<child id="123"/></node> ReadOuterXml Zwraca: <node>this<child id="123"/></node> |
Konwertowanie na typy CLR
Elementy członkowskie XmlReader klasy (wymienione w poniższej tabeli) umożliwiają odczytywanie danych XML i zwracanie wartości jako typów środowiska uruchomieniowego języka wspólnego (CLR) zamiast ciągów. Te elementy członkowskie umożliwiają uzyskanie wartości w reprezentacji, która jest najbardziej odpowiednia dla zadania kodowania bez konieczności ręcznego analizowania lub konwertowania wartości ciągów.
Metody ReadElementContentAs można wywoływać tylko w typach węzłów elementów. Tych metod nie można używać w elementach zawierających elementy podrzędne lub mieszaną zawartość. Po wywołaniu XmlReader obiekt odczytuje tag startowy, odczytuje zawartość elementu, a następnie przechodzi obok tagu elementu końcowego. Instrukcje przetwarzania i komentarze są ignorowane, a jednostki są rozszerzane.
Metody ReadContentAs odczytują zawartość tekstowa na bieżącej pozycji czytnika, a jeśli dane XML nie mają skojarzonych z nim żadnych informacji o schemacie lub typie danych, przekonwertuj zawartość tekst na żądany typ zwracany. Tekst, biały znak, znaczące odstępy i sekcje CDATA są łączone. Komentarze i instrukcje przetwarzania są pomijane, a odwołania do jednostek są automatycznie rozwiązywane.
Klasa XmlReader używa reguł zdefiniowanych przez rekomendację Schemat XML W3C — część 2: Zalecenia dotyczące typów danych.
Użyj tej XmlReader metody | Aby zwrócić ten typ CLR |
---|---|
ReadContentAsBoolean i ReadElementContentAsBoolean | Boolean |
ReadContentAsDateTime i ReadElementContentAsDateTime | DateTime |
ReadContentAsDouble i ReadElementContentAsDouble | Double |
ReadContentAsLong i ReadElementContentAsLong | Int64 |
ReadContentAsInt i ReadElementContentAsInt | Int32 |
ReadContentAsString i ReadElementContentAsString | String |
ReadContentAs i ReadElementContentAs | Typ określony za pomocą parametru returnType |
ReadContentAsObject i ReadElementContentAsObject | Najbardziej odpowiedni typ, określony przez XmlReader.ValueType właściwość . Aby uzyskać informacje o mapowaniu, zobacz Obsługa typów w klasach System.Xml. |
Jeśli nie można łatwo przekonwertować elementu na typ CLR ze względu na jego format, możesz użyć mapowania schematu, aby zapewnić pomyślną konwersję. W poniższym przykładzie użyto pliku xsd do przekonwertowania hire-date
elementu na xs:date
typ, a następnie użyto ReadElementContentAsDateTime metody , aby zwrócić element jako DateTime obiekt.
Dane wejściowe (hireDate.xml):
<employee xmlns="urn:empl-hire">
<ID>12365</ID>
<hire-date>2003-01-08</hire-date>
<title>Accountant</title>
</employee>
Schemat (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>
Kod:
// 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
Wyjście:
Six Month Review Date: 7/8/2003 12:00:00 AM
Programowanie asynchroniczne
XmlReader Większość metod ma asynchroniczne odpowiedniki, które mają wartość "Async" na końcu nazw metod. Na przykład asynchroniczny odpowiednik elementu ReadContentAsObject to ReadContentAsObjectAsync.
Następujące metody mogą być używane z wywołaniami metody asynchronicznej:
- GetAttribute
- MoveToAttribute
- MoveToFirstAttribute
- MoveToNextAttribute
- MoveToElement
- ReadAttributeValue
- ReadSubtree
- ResolveEntity
W poniższych sekcjach opisano asynchroniczne użycie metod, które nie mają asynchronicznych odpowiedników.
ReadStartElement, metoda
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, metoda
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, metoda
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, metoda
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, metoda
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
Zagadnienia dotyczące zabezpieczeń
Podczas pracy z klasą XmlReader należy wziąć pod uwagę następujące kwestie:
Wyjątki zgłaszane przez program XmlReader mogą ujawniać informacje o ścieżkach, których możesz nie chcieć umieścić w aplikacji. Aplikacja musi przechwytywać wyjątki i odpowiednio je przetwarzać.
Nie włączaj przetwarzania DTD, jeśli martwisz się o problemy z odmową usługi lub jeśli masz do czynienia z niezaufanymi źródłami. Przetwarzanie DTD jest domyślnie wyłączone dla XmlReader obiektów utworzonych przez metodę Create .
Jeśli masz włączone przetwarzanie DTD, możesz użyć polecenia XmlSecureResolver , aby ograniczyć zasoby, do których XmlReader można uzyskać dostęp. Możesz również zaprojektować aplikację, aby przetwarzanie XML było ograniczone pamięci i czasu. Możesz na przykład skonfigurować limity czasu w aplikacji ASP.NET.
Dane XML mogą zawierać odwołania do zasobów zewnętrznych, takich jak plik schematu. Domyślnie zasoby zewnętrzne są rozwiązywane przy użyciu XmlUrlResolver obiektu bez poświadczeń użytkownika. Możesz to dodatkowo zabezpieczyć, wykonując jedną z następujących czynności:
Ogranicz zasoby, do których XmlReader może uzyskiwać dostęp, ustawiając XmlReaderSettings.XmlResolver właściwość na XmlSecureResolver obiekt.
Nie zezwalaj XmlReader na otwieranie żadnych zasobów zewnętrznych przez ustawienie XmlReaderSettings.XmlResolver właściwości na
null
.
Flagi ProcessInlineSchemaXmlReaderSettings i ProcessSchemaLocation walidacji obiektu nie są domyślnie ustawione. Pomaga to chronić XmlReader przed atakami opartymi na schemacie podczas przetwarzania danych XML z niezaufanego źródła. Gdy te flagi są ustawione, XmlResolverXmlReaderSettings obiekt jest używany do rozpoznawania lokalizacji schematu napotkanych w dokumencie wystąpienia w XmlReaderpliku . XmlResolver Jeśli właściwość jest ustawiona na
null
, lokalizacje schematu nie są rozpoznawane, nawet jeśli ProcessInlineSchema flagi i ProcessSchemaLocation walidacji są ustawione.Schematy dodane podczas walidacji dodają nowe typy i mogą zmienić wynik weryfikacji weryfikowanego dokumentu. W związku z tym schematy zewnętrzne powinny być rozpoznawane tylko z zaufanych źródeł.
Zalecamy wyłączenie flagi ProcessIdentityConstraints podczas weryfikowania niezaufanych, dużych dokumentów XML w scenariuszach wysokiej dostępności względem schematu, który ma ograniczenia tożsamości w dużej części dokumentu. Ta flaga jest domyślnie włączona.
Dane XML mogą zawierać dużą liczbę atrybutów, deklaracji przestrzeni nazw, zagnieżdżonych elementów itd., które wymagają znacznego czasu na przetworzenie. Aby ograniczyć rozmiar danych wejściowych wysyłanych do XmlReaderelementu , możesz:
Ogranicz rozmiar dokumentu, ustawiając MaxCharactersInDocument właściwość .
Ogranicz liczbę znaków, które wynikają z rozszerzania jednostek, ustawiając MaxCharactersFromEntities właściwość .
Utwórz niestandardową
IStream
implementację dla elementu XmlReader.
Metoda ReadValueChunk może służyć do obsługi dużych strumieni danych. Ta metoda odczytuje niewielką liczbę znaków jednocześnie zamiast przydzielać jeden ciąg dla całej wartości.
Podczas odczytywania dokumentu XML z dużą liczbą unikatowych nazw lokalnych, przestrzeni nazw lub prefiksów może wystąpić problem. Jeśli używasz klasy, która pochodzi z XmlReaderklasy , i wywołujesz LocalNamewłaściwość , Prefixlub NamespaceURI dla każdego elementu, zwracany ciąg zostanie dodany do NameTableelementu . Kolekcja przechowywana przez element nigdy nie zmniejsza rozmiaru NameTable , tworząc wirtualny wyciek pamięci uchwytów ciągów. Jednym z środków zaradczych jest wyprowadzenie z NameTable klasy i wymuszenie maksymalnego limitu przydziału rozmiaru. (Nie ma możliwości zapobiegania używaniu NameTableobiektu lub przełączania NameTable , gdy jest pełny). Innym ograniczeniem jest unikanie używania wymienionych właściwości, a zamiast tego należy użyć MoveToAttribute metody z IsStartElement metodą tam, gdzie to możliwe. Metody te nie zwracają ciągów, a tym samym uniknąć problemu nadmiernego NameTable wypełniania kolekcji.
XmlReaderSettings obiekty mogą zawierać poufne informacje, takie jak poświadczenia użytkownika. Niezaufany składnik może używać XmlReaderSettings obiektu i jego poświadczeń użytkownika do tworzenia XmlReader obiektów do odczytywania danych. Podczas buforowania XmlReaderSettings obiektów lub przekazywania XmlReaderSettings obiektu z jednego składnika do innego należy zachować ostrożność.
Nie akceptuj składników pomocniczych, takich jak NameTable, XmlNamespaceManageri , XmlResolver z niezaufanego źródła.