XML-Dokumente erscheinen je nach Größe auf den ersten Blick oft unübersichtlich und mächtig. Wie soll man hier die gewünschten Daten extrahieren – und das auch noch programmgesteuert per VBA Beispielsweise, um Informationen aus einem XML-Dokument in eine Access-Tabelle zu übertragen. Dafür steht die Abfragesprache VBA XPath zur Verfügung. Sie erlaubt es, mit verschiedenen Ausdrucken gezielt auf Elemente mit bestimmten Namen oder Eigenschaften zuzugreifen. Dieser Beitrag zeigt anhand einiger Beispiele, wie Sie XPath unter Access/VBA einsetzen.
Voraussetzungen für VBA XPath
Um die folgenden Beispiele auszuführen, benötigen Sie eine Beispieldatenbank mit einem Verweis auf die XML-Bibliothek von Microsoft. Dazu öffnen Sie den Verweise-Dialog (VBA-Editor, Menüeintrag Extras|Verweise) und wählen dort den Eintrag Microsoft XML, v3.0 aus (s. Bild 1). Mit Microsoft XML, v6.0 gab es bei der Erstellung der Beispiele Probleme, da hier einige Methoden nicht die erwarteten Ergebnisse lieferten.
Bild 1: Hinzufügen des Verweises auf die XML-Bibliothek
Beispieldokument
Um per VBA XPath auf den Inhalt eines XML-Dokuments zugreifen zu können, benötigen Sie zunächst ein solches. Unseres heißt KategorienUndArtikel.xml und sollte sich im gleichen Verzeichnis wie die Beispieldatenbank befinden, da die Zugriffe auf diese Datei dahingehend ausgerichtet sind. Der Inhalt dieser XML-Datei sieht wie in Listing 1 aus.
<xml version="1.0" encoding="UTF-16"> <Bestellverwaltung xmlns="http://www.w3.org/TR/REC-html40"> <Kategorie KategorieID="1"> <Kategoriename>Getränke</Kategoriename> <Beschreibung>Alkoholfreie Getränke, Kaffee, Tee, Bier</Beschreibung> <Artikel ArtikelID="1"> <Artikelname>Chai</Artikelname> <Einzelpreis>EUR 9.00</Einzelpreis> </Artikel> <Artikel ArtikelID="2"> <Artikelname>Chang</Artikelname> <Einzelpreis>EUR 9.50</Einzelpreis> </Artikel> .. </Kategorie> <Kategorie KategorieID="2"> <Kategoriename>Gewürze</Kategoriename> <Beschreibung>Süße und saure Soßen, Gewürze</Beschreibung> <Artikel ArtikelID="3"> <Artikelname>Aniseed Syrup</Artikelname> <Einzelpreis>EUR 5.00</Einzelpreis> </Artikel> <Artikel ArtikelID="4"> <Artikelname>Chef Anton''''s Cajun Seasoning</Artikelname> <Einzelpreis>EUR 11.00</Einzelpreis> </Artikel> ... </Kategorie> ... </Bestellverwaltung>
Listing 1: XML-Dokument für die Beispiele dieses Beitrags
Zugriff mit VBA XPath über den Speicher
Um per VBA XPath auf ein XML-Dokument zugreifen zu können, müssen Sie dieses zunächst in den Speicher laden, beziehungsweise es mit einem geeigneten Objekt referenzieren. Dies erledigen Sie mit dem Code, wie er etwa in der folgenden Prozedur enthalten ist:
Public Sub DokumentLaden() Dim strDatei As String Dim objXML As MSXML2.DOMDocument strDatei = CurrentProject.Path & "KategorienUndArtikel.xml" Set objXML = New MSXML2.DOMDocument objXML.Load strDatei If Not Len(objXML.XML) = 0 Then Debug.Print objXML.XML Else Debug.Print objXML.parseError.errorCode, objXML.parseError.reason End If End Sub
Die Prozedur erstellt ein neues Objekt des Typs DOMDocument und verwendet die Load-Methode, um die angegebene Datei in das Objekt zu laden. Gelingt dies, sollte die Länge der über die Eigenschaft XML zu ermittelnde Zeichenkette, also der Inhalt des Dokuments, größer als 0 sein. In diesem Fall soll die Prozedur den Inhalt des XML-Dokuments im Direktbereich des VBA-Editors ausgeben. Anderenfalls ist etwas beim Einlesen schiefgelaufen. Dann soll die Fehlernummer samt der Fehlerbeschreibung im Direktbereich erscheinen.
XPath per VBA nutzen
Um die Abfragesprache XPath von VBA aus nutzen zu können, gibt es zwei Funktionen. Die erste heißt selectSingleNode und erwartet einen XPath-Ausdruck als Parameter. Sie liefert ein einziges Node-Element als Ergebnis zurück, sofern die Abfrage ein Ergebnis hat.
Die zweite Funktion heißt selectNodes und liefert eine Auflistung des Typs DOMSelection zurück. Sie kann kein, ein oder mehrere Elemente enthalten, die wiederum den Typ DOMDocument für das Dokument-Objekt, IXMLDOMProcessingInstruction für das -Element oder IXMLDOMElement für die übrigen Elemente aufweisen.
üblicherweise werden Sie aber mit den Elementen des Typs IXMLDOMElement arbeiten, ein Zugriff auf das DOMDocument-Objekt oder das IXMLDOMProcessingInstruction-Objekt ist selten in Zusammenhang mit dem Zugriff per XPath nötig.
Unsere Beispielprozedur für das Erstellen eines XML-Dokuments und das Füllen dieses Objekts aus einer XML-Datei haben wir etwas abgewandelt, damit wir damit mit einer Anweisung innerhalb unserer Beispielprozeduren auf das XML-Dokument zugreifen können (s. Listing 2).
Public Function GetDocument() As MSXML2.DOMDocument Dim strDatei As String Dim objXML As MSXML2.DOMDocument strDatei = CurrentProject.Path & "KategorienUndArtikel.xml" Set objXML = New MSXML2.DOMDocument objXML.Load strDatei If Not Len(objXML.XML) = 0 Then Set GetDocument = objXML Else MsgBox "Fehler " & objXML.parseError.errorCode & ": " & objXML.parseError.reason End If End Function
Listing 2: Hilfsfunktion, um ein gefülltes DOMDocument-Element zu holen
Auf das Root-Element zugreifen
Ein Beispiel für den Zugriff auf ein einzelnes XML-Element sieht danach wie folgt aus:
Public Sub RootelementHolen() Dim objElement As MSXML2.IXMLDOMElement Dim objDocument As MSXML2.DOMDocument Set objDocument = GetDocument Set objElement = _ objDocument.selectSingleNode("Bestellverwaltung") Debug.Print objElement.XML End Sub
Dies liest das Element Bestellverwaltung samt allen untergeordneten Elementen ein. Wenn wir wie in obiger Beispielprozedur den Inhalt der XML-Eigenschaft im Direktbereich ausgeben, erhalten wir also fast das komplette Dokument – mit Ausnahme der Formatinformationen in der -Zeile.
Dies gelingt aber auch nur über den VBA XPath-Ausdruck Bestellverwaltung, weil wir die selectSingleNode-Funktion für das DOMDocument-Objekt aufrufen und das Bestellverwaltung-Objekt diesem direkt untergeordnet ist.
Wir könnten also nicht etwa auf das erste Kategorie-Objekt zugreifen, indem wir einfach folgenden Ausdruck nutzen:
Set objElement = objDocument.selectSingleNode("Kategorie")
Wenn wir dies versuchen, erhalten wir eine Fehlermeldung wie in Bild 2. Die Anweisung Set objElement… löst zwar noch keinen Fehler aus. Aber objElement wird hier nicht gefüllt und der folgende Zugriff auf eine Eigenschaft von objElement führt dann zum Fehler.
Bild 2: Fehler beim Zugriff auf ein XML-Element
Auf ein direktes Unterelement des Root-Elements zugreifen
Mit dem Namen eines Elements allein können Sie also nur auf ein Element zugreifen, wenn sich dieses direkt unterhalb des Objekts befindet, für das Sie die SelectSingleNode-Methode aufrufen.
Dafür müssten Sie zuerst das Root-Element Bestellverwaltung per IXMLDomElement-Variable referenzieren und könnten dann von dort aus auf das Kategorie-Element zugreifen:
Dim objBestellverwaltung As MSXML2.IXMLDOMElement Dim objKategorie As MSXML2.IXMLDOMElement Dim objDocument As MSXML2.DOMDocument Set objDocument = GetDocument Set objBestellverwaltung = objDocument.selectSingleNode("Bestellverwaltung") Set objKategorie = objBestellverwaltung. selectSingleNode("Kategorie") Debug.Print objKategorie.XML
Dies gibt den Inhalt des ersten Kategorie-Elements aus.
An dieser Stelle ist es wichtig zu erwähnen, dass die SelectSingleNode immer das erste Element liefert, das dem angegebenen Ausdruck entspricht. Während es nur ein Bestellverwaltung-Element gibt, befinden sich darunter allerdings gleich sieben Kategorie-Elemente. Davon liefert SelectSingleNode dann das erste.
Auf mehrere Elemente zugreifen
Das ist ein guter Anlass, die Funktion selectNodes vorzustellen. Sie liefert nicht nur ein einziges Element zurück, sondern kann auch einmal kein oder mehrere Elemente zurückgeben. Diese kommen immer in einer Auflistung vom Typ DOMSelection.
Wenn Sie die gefundenen Elemente mit der For Each-Schleife durchlaufen wollen, definieren Sie wie im folgenden Beispiel sowohl ein Objekt namens objKategorie mit dem Typ IXMLDOMElement als Laufvariable sowie eines für die Auflistung namens objKategorien mit dem Typ IXMLDOMSelection.
Dann referenzieren Sie wieder das Root-Element und nutzen dann dessen selectNodes-Funktion, um alle untergeordneten Kategorie-Elemente zu ermitteln. Diese landen dann im Auflistungsobjekt objKategorien. Dieses können wir dann per For Each-Schleife mit der Laufvariablen objKategorie durchlaufen. Innerhalb der Schleife geben wir wieder den Inhalt der XML-Eigenschaft aus:
Public Sub KategorienHolen() Dim objBestellverwaltung As MSXML2.IXMLDOMElement Dim objKategorie As MSXML2.IXMLDOMElement Dim objKategorien As MSXML2.IXMLDOMSelection Dim objDocument As MSXML2.DOMDocument Set objDocument = GetDocument Set objBestellverwaltung = objDocument.selectSingleNode("Bestellverwaltung") Set objKategorien = objBestellverwaltung.selectNodes("Kategorie") For Each objKategorie In objKategorien Debug.Print objKategorie.XML Next objKategorie End Sub
Da die Ausgabe alle Kategorie-Elemente umfasst, die selbst jeweils einige Artikel-Elemente enthalten, sprengt die Ausgabe das Direktfenster. Also geben wir etwas weniger Umfangreiches aus, indem wir die Debug.Print-Anweisung wie folgt ersetzen und damit gleich noch einen einfachen XPath-Ausdruck nutzen:
Debug.Print objKategorie.selectSingleNode( "Kategoriename").nodeTypedValue
Da wir in diesem Fall nicht einfach den Inhalt der Eigenschaft XML ausgeben wollen, sondern den Inhalt des Elements Kategoriename selbst, verwenden wir die Eigenschaft nodeTypedValue.
Die gefundenen Elemente können Sie auch per For…Next-Schleife durchlaufen. Dann nutzen Sie die length-Eigenschaft der IXMLDOMSelection-Auflistung zur Bestimmung der Anzahl der Elemente.
über die Item()-Eigenschaft greifen Sie dann auf das jeweilige Element zu, wobei der Index 0-basiert ist, was für den Wertebereich der Schleife berücksichtigt werden muss:
Dim i As Integer ... Set objKategorien = objBestellverwaltung.selectNodes("Kategorie") For i = 0 To objKategorien.length - 1 Debug.Print objKategorien.Item(i).selectSingleNode( "Kategoriename").nodeTypedValue Next i
Beispiele für XPath-Ausdrücke
Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...
Oder bist Du bereits Abonnent? Dann logge Dich gleich hier ein. Die Zugangsdaten findest Du entweder in der aktuellen Print-Ausgabe auf Seite U2 oder beim Online-Abo in der E-Mail, die Du als Abonnent regelmäßig erhältst:
Weitere interessante Artikel zu diesem Thema
Daten im XML-Format exportieren und weiterverarbeiten