Die Community zu .NET und Classic VB.

XML-Dateien lesen mit Hilfe der Microsoft XML Library

 von 

Ü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 ()

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.