XML-Dateien lesen mit Hilfe der Microsoft XML Library
von Hendrik Storck
Übersicht
Dieses Tutorial erläutert die Verwendung der Microsoft XML Library um XML-Dateien zu lesen. Als Beispiel soll hier das Auslesen einer kleinen Adressdatei im XML-Format stehen. Ziel ist es die grundlegenden Funktionen zum Auslesen und Durchsuchen von XML-Dateien zu vermitteln.
Mit freundlichen Grüßen
Hendrik Storck (gdis@arcor.de)
Einbinden der XML Object Library
Um die XML Bibliothek verwenden zu können, muss diese dem Projekt hinzugefügt werden. Dazu fügen Sie über Projekt | Verweise einen Verweis auf die "Microsoft XML x.0" Library hinzu. Ich verwende für dieses Tutorial die Version 3.0.
Die Beispieldatei
<?xml version="1.0" encoding="windows-1252"?>
<Adressen>
<Kontakt ID="1">
<Vorname>Max</Vorname>
<Name>Mustermann</Name>
<Strasse>Musterweg 4</Strasse>
<Ort>Musterhausen</Ort>
<PLZ>12345</PLZ>
<Telefon>0123456789</Telefon>
</Kontakt>
<Kontakt ID="2">
<Vorname>Maxima</Vorname>
<Name>Musterfrau</Name>
<Strasse>Musterstrasse 2</Strasse>
<Ort>Musterdorf</Ort>
<PLZ>45836</PLZ>
<Telefon>032453529</Telefon>
</Kontakt>
</Adressen> Listing 1
Laden einer XML-Datei
Bevor wir die XML-Datei verwenden können, benötigen wir ein XML-DOM-Objekt, mit dem wir eine Datei laden können. Ich verwende für die Beispiele hier ein globales Objekt:
Option Explicit Dim objXML As MSXML2.DOMDocument40 Private Sub Form_Load() Set objXML = New MSXML2.DOMDocument40 ' Struktur des Dokumentes beim Laden prüfen objXML.validateOnParse = True ' Dokument laden If Not objXML.Load(App.Path & "\demo.xml") Then ' Fehler beim Laden MsgBox "Fehler beim Laden des Dokumentes." & vbCrLf & vbCrLf _ & "Grund: " & objXML.parseError.reason & vbCrLf _ & "Zeile: " & objXML.parseError.Line, vbOKOnly Or vbExclamation, "Fehler" Set objXML = Nothing End If End Sub Private Sub Form_Unload(Cancel As Integer) ' Aufräumen Set objXML = Nothing End Sub
Listing 2
Zugriff auf den XML-Quelltext
Der Zugriff auf den XML-Quelltext gestaltet sich sehr einfach:
Debug.Print objXML.xml
Listing 3
Zugriff auf ein bestimmtes Element (Node)
Häufig will man auf ein bestimmtes Element (Knoten oder auch Node) zugreifen. Dies wird über die Methode selectSingleNode des documentElements-Objektes realisiert.
Als Parameter wird hier der "Pfad" zum gewünschten Knoten angegeben (
XPath):
Debug.Print objXML.documentElement.selectSingleNode("/Adressen/Kontakt").text
Listing 4
Dies gibt alle Informationen dieses Knotens aus. Besteht der Knoten aus mehreren Elementen (wie in dem obigen Beispiel), so werden auch die Werte der Child-Knoten ausgegeben.
Der Zugriff auf ein bestimmtes Element eines Objektes (z.B. auf den Namen eines Kontaktes) erfolgt nach dem gleichen Muster; es wird nur ein zusätzlicher Parameter (nämlich der Name des Elementes) angegeben:
Debug.Print objXML.documentElement.selectSingleNode("/Adressen/Kontakt/Name").text
Listing 5
Zu beachten ist, dass dieser Befehl nur den Namen des ersten Kontakt-Objektes in der Aufzählung wiedergibt.
Zusätzlich gibt es die Möglichkeit auf ein Element mit einem bestimmten Index zuzugreifen. Dazu wird dieser in eckigen Klammern angegeben:
Debug.Print objXML.documentElement.selectSingleNode("/Adressen/Kontakt[1]/Name").text
Listing 6
Zu beachten ist, dass der Index bei 0 beginnt. Will man auf ein Element eines ganz bestimmten Objektes zugreifen, so muss der Aufruf wie folgt umgeschrieben werden:
Debug.Print objXml.documentElement.selectSingleNode("/Adressen/Kontakt[Vorname='Max']/Strasse").text
Listing 7
Dieses Beispiel liefert die Strasse des Kontaktes mit dem Vornamen "Max". Zu beachten ist, dass – sollte der Vorname mehrfach vorkommen – nur der erste Eintrag zurückgegeben wird. Ebenso können mehrere Parameter für die Auswahl eines Objektes angegeben werden:
Debug.Print objXml.documentElement.selectSingleNode("/Adressen/Kontakt[Vorname='Max'][Name='Mustermann']/Strasse").text
Listing 8
Zugriff auf Attribute eines Knotens
Häufig enthalten Knoten zusätzliche Informationen, die im selben Knoten angegeben werden (sogenannte Attribute):
<Kontakt ID="1">
Diese stellt die MSXML über die Attribute-Collection zur Verfügung.
Mit nachfolgendem Beispiel lässt sich z.B. die Anzahl der Attribute eines Elements ausgeben:
Debug.Print objXml.documentElement.selectSingleNode("/Adressen/Kontakt[Vorname='Max']/Strasse").attributes.length
Listing 9
Über Angabe eines Index kann man auch auf ein bestimmtes Attribut zugreifen:
Debug.Print objXml.documentElement.selectSingleNode("/Adressen/Kontakt[0]").Attributes(0).text
Listing 10
Das nachfolgende Beispiel gibt die Namen aller Attribute des ersten Kontaktes sowie deren Wert aus:
Dim i As Long Dim aNode As IXMLDOMNode Set aNode = objXml.documentElement.selectSingleNode("/Adressen/Kontakt[0]") For i = 0 To aNode.Attributes.length 1 Debug.Print aNode.Attributes(i).nodeName & : & _ aNode.Attributes(i).Text Next i Set aNode = Nothing
Listing 11
MSXML gestattet den Zugriff auf Attributes (soweit mir bekannt ist) nur über die Angabe eines Indexes ( Update : Es ist möglich, mittels node.attributes.getNamedItem('name_des_Attribut').nodeValue auf ein Attribut zuzugreifen). Dies ist sinnvoll, da XML-Dateien normalerweise einem festgelegten Schema entsprechen, über welches die Reihenfolge der Attribute festgelegt ist.
Da es aber unter Umständen einfacher ist, auf ein Attribut über seinen Namen zuzugreifen (Lesbarkeit des Quellcodes), schreiben wir uns eine kleine Hilfsfunktion, welche uns das Attribut anhand des Namens zurückgibt:
' Funktion in einem Modul Public Function GetNodeAttributeByName(ByRef oNode As IXMLDOMNode, ByVal sName As String) As IXMLDOMAttribute Dim i As Long For i = 0 To oNode.Attributes.length 1 If Lcase$(oNode.Attributes(i).nodeName) = Lcase$(sName) Then Set GetNodeAttributeByName = oNode.Attributes(i) Exit Function End If Next i End Function
Listing 12
Alternativ könnte die Methode natürlich auch nur den Index zurückliefern. Dank dieser Methode sind wir nun in der Lage auf das Attribut eines Knotens über seinen Namen zuzugreifen:
Debug.Print GetNodeAttributeByName(aNode, "ID").text
Listing 13
Aufgrund der Fehleranfälligkeit bietet sich jedoch an, erst zu prüfen, ob die Funktion tatsächlich ein Attribut zurückgegeben hat:
Dim anAttribute As IXMLDOMAttribute Set anAttribute = GetNodeAttributeByName(aNode, "ID") If Not anAttribute Is Nothing Then Debug.Print anAttribute.text Set anAttribute = Nothing End If
Listing 14
Der Zugriff auf ein Attribut kann aber auch durch Angabe des XPath geschehen. Attribute werden dabei durch ein @ (gefolgt vom Namen des Attributes) gekennzeichnet. Um also den Wert des ID-Attributes des ersten Kontakts zu ermitteln schreiben wir:
Debug.Print objXml.documentElement.selectSingleNode("/Adressen/Kontakt[0]/@ID").Text
Listing 15
Ebenso kann man Attribute verwenden, um auf ein bestimmtes Element zuzugreifen. So können wir z.B. den Vornamen des Kontaktes ausgeben, bei dem das ID-Attribut auf "1" gesetzt ist:
Debug.Print objXml.documentElement.selectSingleNode("/Adressen/Kontakt[@ID='1']/Vorname").Text
Listing 16
Zugriff auf Node-Collections
Eine andere häufig benutzte Methode besteht darin alle Objekte eines bestimmten Typs aufzulisten. In unserem Beispiel, sollen z.B. alle Kontakte in einer Liste dargestellt werden.
Wenn wir uns die XML-Datei ansehen, so fällt auf, dass alle Kontakte in einer Collection namens "Adressen" gespeichert sind. Diese lässt sich mit einer einfachen For...Each-Schleife auslesen:
Dim einKontakt As IXMLDOMNode For Each einKontakt In objXML.documentElement.selectSingleNode("/Adressen").childNodes List1.AddItem einKontakt.childNodes(0).Text Next
Listing 17
Zu beachten ist auch hier, dass der Zugriff auf eine Child-Node nur durch Angabe eines Indizes erfolgen kann. Natürlich könnten wir uns auch hier wieder eine Hilfsfunktion schreiben, die es ermöglicht den Index anhand des Namens zurückzuliefern.
Alternativ stellt MSXML auch eine NodeList zur Verfügung, die eine solche Node-Collection speichern kann:
Dim alleKontakte As IXMLDOMNodeList Set alleKontakte = objXML.documentElement.selectSingleNode("/Adressen").childNodes For Each einKontakt In alleKontakte List1.AddItem einKontakt.childNodes(0).Text Next
Listing 18
Natürlich besteht auch die Möglichkeit, nur bestimmte Elemente einer Collection aufzulisten (hier etwa das Element mit der ID "1")
Dim alleKontakte As IXMLDOMNodeList Set alleKontakte = objXML.documentElement. selectNodes("/Adressen/Kontakt[@ID='1']") For Each einKontakt In alleKontakte List1.AddItem einKontakt.childNodes(0).Text Next
Listing 19
Schlusswort
Ich hoffe mit diesem kurzen Tutorial einen kleinen Einblick in die grundleglegende Verwendung der MSXML-Library gegeben zu haben.
Natürlich konnten im Rahmen des Tutorials nicht alle Möglichkeiten von MSXML gezeigt werden, aber die Basisfunktionen zum Auslesen einer XML-Datei sollten ein guter Anfang sein.
Mit freundlichem Gruß
Hendrik Storck
Ihre Meinung
Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.

