XML-Dokumente schnell lesen mit XmlReader

Unter .NET gibt es verschiedene Methoden und Klassen, mit denen Sie auf die Daten in XML-Dokumenten zugreifen können. Diese nutzen Sie je nach Einsatzzweck. Wenn Sie sehr große Dateien einlesen wollen, bietet sich die XmlReader-Klasse an. Mit dieser durchlaufen Sie das XML-Dokument sequenziell, das heißt, Element für Element. Dieser Artikel zeigt, wie Sie mit den Methoden der XmlReader-Klasse auf die Elemente eines XML-Dokuments zugreifen. Außerdem schauen wir uns an, wie Sie die eingelesen Inhalte in Objekte schreiben können, über die Sie die Inhalte dann in die Tabellen einer Datenbank eintragen.

Wer unter Access/VBA auf XML-Dokumente zugegriffen hat, hat dazu in der Regel das Document Object Model verwendet und dabei die Elemente mit den gewünschten Daten gezielt angesteuert. Unter VBA gibt es noch eine weitere Technik namens SAX. Diese ist recht kompliziert und wird sehr selten verwendet. Dieser Technik kommt der hier verwendete XmlReader jedoch recht nahe. Seine Handhabung ist allerdings einfacher als bei SAX.

Dokument öffnen

Um ein XML-Dokument zu öffnen, benötigen wir ein Objekt auf Basis der XMLReader-Klasse. Diese ist Teil des Namespaces System.XML, den wir mit der folgenden Anweisung etwa in der Code behind-Klasse eines Fensters einer neuen Desktop-Anwendung auf Basis von XAML und VB referenzieren:

Imports System.Xml

Danach können wir auf die XmlReader-Klasse und ihre Elemente zugreifen. Bei der Klasse handelt es sich um eine abstrakte Klasse, das heißt, Sie können diese nicht instanzieren. Wir können aber dennoch eine Objektvariable nutzen, um auf das zu lesende XML-Dokument zuzugreifen. Um ein XML-Dokument zu öffnen, das auf der Festplatte liegt, verwenden Sie die Create-Methode. Dieser übergeben wir den Pfad zu der einzulesenden XML-Datei:

Dim objReader As XmlReader
Dim strPfad As String
strPfad = "c:\...\Kunden.xml"
objReader = XmlReader.Create(strPfad)

Danach befindet sich das XML-Dokument im Zugriff. Wir schauen uns die Funktionsweise der Klasse XmlReader anhand des folgenden XML-Dokuments an:

<xml version="1.0" encoding="utf-8">
<Bestellverwaltung>
   <!--Auflistung der Kunden-->
   <Kunden>
     <Kunde ID="1">
       <Firma>André Minhorst Verlag</Firma>
       <Vorname>André</Vorname>
       <Nachname>Minhorst</Nachname>
       <Beschreibung><![CDATA[Beschreibung mit CDATA]]></Beschreibung>
     </Kunde>
     <Kunde ID="2">
       <Firma>Müller GmbH</Firma>
       <Vorname>Klaus</Vorname>
       <Nachname>Müller</Nachname>
     </Kunde>
   </Kunden>
</Bestellverwaltung>

XML-Dokument sequenziell durchlaufen mit Read

Im Gegensatz zum Durchlaufen einer Textdatei durchlaufen wir hier nicht Zeile für Zeile, sondern Element für Element. Ein Element ist dabei nicht etwa eine Einheit wie André. In diesem Fall sind , André und jeweils ein Element. Auch der Prolog des XML-Dokuments ist ein eigenes Element. Auf diese Elemente greifen wir mit der Read-Methode zu. Nachdem wir diese erstmals aufgerufen haben, referenziert objReader das erste Element, in diesem Fall den Prolog. Danach geht es weiter mit den folgenden Elementen – also den Starttags, den enthaltenen Texten, den Endtags und auch den leeren Elementen dazwischen, den sogenannten Whitespace-Elementen. Wie erkennen wir nun, welchen Elementtyp objReader gerade geladen hat Dazu können wir die Eigenschaft NodeType verwenden. Diesen lassen wir uns in einer ersten Schleife ausgeben:

Do While objReader.Read
     Debug.Print(objReader.NodeType)
Loop

Wir durchlaufen also alle Elemente in einer Do While-Schleife, deren Abbruch objReader.Read lautet. Die Read-Methode liefert den Wert True zurück, falls noch ein neues Element eingelesen werden konnte und den Wert False, wenn das Ende des Dokuments erreicht wurde. Das Ergebnis der Ausgabe ist wenig aussagekräftig, denn NodeType liefert einen Zahlenwert (siehe Bild 1).

Elementtypen

Bild 1: Elementtypen

Welcher Wert entspricht nun welchem Elementtyp Das können wir uns im Objektkatalog ansehen, wo wir nach der Eigenschaft NodeType suchen und den Eintrag System.Xml.XmlNodeType vorfinden. Beim Anklicken der Elemente zeigt der Dialog auch die Zahlenwerte an, die wir mit denen unserer Ausgabe abgleichen können (siehe Bild 2).

Elementtypen im Objektkatalog

Bild 2: Elementtypen im Objektkatalog

Also reichern wir unsere Do While-Schleife um eine Select Case-Bedingung an, welche den Typ ermittelt und diesen im Direktbereich ausgibt. Für uns sind die folgenden Elementtypen interessant:

  • Attribute: Attribut
  • CDATA: Block mit einem CDATA-Abschnitt
  • Comment: Kommentar, zum Beispiel
  • Element: Starttag, zum Beispiel
  • EndElement: Endtag, zum Beispiel
  • Text: Text in einem Element
  • Whitespace: Leerraum zwischen Elementen
  • XmlDeclaration: XML-Deklarationszeile, zum Beispiel

In der folgenden Schleife geben wir die Typen der Elemente unseres Dokuments aus:

Do While objReader.Read
     Select Case objReader.NodeType
         Case XmlNodeType.XmlDeclaration
             Debug.Print("XmlDeclaration")
         Case XmlNodeType.Element
             Debug.Print("Element")
         Case XmlNodeType.EndElement
             Debug.Print("EndElement")
         Case XmlNodeType.Whitespace
             Debug.Print("Whitespace")
         Case XmlNodeType.Text
             Debug.Print("Text")
         Case Else
             Debug.Print(objReader.NodeType)
     End Select
Loop

Nun wollen wir für die unterschiedlichen Elementtypen entsprechende Ausgaben bewirken. Diese erhalten wir über die Eigenschaften des aktuellen Elements. NodeType war die erste Eigenschaft, die Sie kennengelernt haben. Es gibt jedoch noch weitere Eigenschaften, die für uns interessant sein können:

  • Depth: Tiefe des aktuellen Elements in der Hierarchie
  • IsStartElement: Gibt an, ob das aktuelle Element ein Starttag ist. Der folgende Code gibt beispielsweise alle Namen von Starttags aus:
         Do While objReader.Read
             If (objReader.IsStartElement) Then
                 Debug.Print(objReader.Name)
             End If
         Loop
  • Name: Name des Elements. Vor allem interessant bei den Elementtypen Element und EndElement.
  • NodeType: Typ des Elements
  • Value: Wert des Elements, vor allem interessant bei den Elementtypen Text oder Comment.
  • IsEmptyElement: Gibt an, ob das Element einen Wert enthält.

Attribute erkennen mit HasAttributes und AttributeCount

Möglicherweise ist Ihnen aufgefallen, das wir zwar die Inhalte der Elemente ausgegeben haben, jedoch noch nicht die der Attribute. Diese erhalten wir auf einem anderen Weg. Grundsätzlich finden wir Attribute nur bei Elementen des Typs Element. Hier können wir mit der Eigenschaft HasAttributes prüfen, ob überhaupt Attribute vorliegen. Ist das der Fall, lässt sich mit der Eigenschaft AttributeCount die Anzahl der Attribute ermitteln. Wir können diese aber auch direkt in einer Do While-Schleife durchlaufen.

Dazu verwenden wir wieder eine Abbruchbedingung, die gleichzeitig das nächste Attribut einliest. Diese lautet MoveToNextAttribut. Die Methode liefert den Wert True, wenn sie ein weiteres Attribut gefunden hat und False, wenn kein weiteres Attribut vorliegt. Den Namen des Attributs ermitteln Sie dann wiederum mit der Eigenschaft Name. Den Wert des Attributs liefert die Eigenschaft Value.

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins DATENBANKENTWICKLER:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 200 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar