XML-Dateien lesen mit Hilfe der Microsoft XML Library bzw mit dem .NET Xml.XmlDocument
von Hendrik Storck
Übersicht
Dieses Tutorial erläutert die Verwendung der Microsoft XML Library und des .NET Xml.XmlDocument Objekts 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.
Erstversion Hendrik Storck (gdis@arcor.de), 2006
Überarbeitung Daniel Aue, 2013
Einbinden der XML Object Library
Um die XML Bibliothek unter VB6 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 6.0 bzw. das .NET Framework 4.0. Alternativ, z.B. in Scripts kann ein DOMDocument Objekt aber auch mittels CreateObject("Microsoft.XMLDOM") erstellt werden.
Die Beispieldatei:
<?xml version="1.0" encoding="windows-1252"?> <Adressen> <Kontakt ID="1" Tags="Freund|Schulkollege"> <Vorname>Max</Vorname> <Name>Mustermann</Name> <Strasse>Musterweg 4</Strasse> <Ort>Musterhausen</Ort> <PLZ>12345</PLZ> <Telefon>0123456789</Telefon> </Kontakt> <Kontakt ID="2" Tags="Freund|Arbeitskollege|Gruppe1"> <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-DOMDocument Objekt, mit dem wir eine Datei laden können. Ich verwende für die Beispiele hier ein globales Objekt:
'VB6 Option Explicit Dim objXML As MSXML2.DOMDocument Private Sub Form_Load() Set objXML = New MSXML2.DOMDocument 'oder: set objXML = CreateObject("Microsoft.XMLDOM") ' Struktur des Dokumentes beim Laden prüfen objXML.validateOnParse = True 'echtes XPath verwenden um Nodes zu selektieren '(default: komplexe XPaths werden nicht unterstützt) objXML.setProperty "SelectionLanguage", "XPath" ' 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
'VB.NET Public Class Form1 Public objXML As Xml.XmlDocument Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load objXML = New Xml.XmlDocument Try objXML.Load(My.Application.Info.DirectoryPath & "\demo.xml") Catch ex As Exception MessageBox.Show("Fehler beim Laden des Dokumentes!", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Sub End Class
Listing 2
Zugriff auf den XML-Quelltext
Der Zugriff auf den XML-Quelltext gestaltet sich sehr einfach:
'VB6 Debug.Print objXML.xml
'VB.NET
Debug.print (objXML.InnerXml)
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 realisiert.
Als Parameter wird hier der "Pfad" zum gewünschten Knoten angegeben (XPath ):
'VB6 Debug.Print objXML.selectSingleNode("/Adressen/Kontakt").text
'VB.NET
debug.Print (objXML.selectSingleNode("/Adressen/Kontakt").InnerText)
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:
'VB6 Debug.Print objXML.selectSingleNode("/Adressen/Kontakt/Name").text
'VB.NET
debug.Print (objXML.selectSingleNode("/Adressen/Kontakt/Name").InnerText)
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:
'VB6 Debug.Print objXML.selectSingleNode("/Adressen/Kontakt[1]/Name").text
'VB.NET
Debug.Print (objXML.selectSingleNode("/Adressen/Kontakt[1]/Name").InnerText)
Listing 6
Will man auf ein Element eines ganz bestimmten Objektes zugreifen, so muss der Aufruf wie folgt umgeschrieben werden:
'VB6 Debug.Print objXml.selectSingleNode("/Adressen/Kontakt[Vorname='Max']/Strasse").text
'VB.NET
Debug.Print (objXml.selectSingleNode("/Adressen/Kontakt[Vorname='Max']/Strasse").InnerText)
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:
'VB6 Debug.Print objXml.selectSingleNode("/Adressen/Kontakt[Vorname='Max'][Name='Mustermann']/Strasse").text
'VB.NET
Debug.Print (objXml.selectSingleNode("/Adressen/Kontakt[Vorname='Max'][Name='Mustermann']/Strasse").innertext)
Listing 8
Da jedoch nicht sichergestellt ist, dass ein angesprochenes Element auch tatsächlich existiert ist es ratsam, erst zu prüfen, ob von SelectSingleNode tatsächlich ein Objekt zurückgegeben wurde:
'VB6 Dim oNode As IXMLDOMNode Set oNode = objXML.SelectSingleNode("/Adressen/Kontakt[Vorname='Karl']/Strasse") If Not oNode Is Nothing Then Debug.Print oNode.Text Else MsgBox "Element nicht gefunden!", vbOKOnly Or vbExclamation, "Fehler" End If
'VB.NET Dim oNode As Xml.XmlNode = objXML.SelectSingleNode("/Adressen/Kontakt[Vorname='Karl']/Strasse") If Not oNode Is Nothing Then Debug.Print(oNode.InnerText) Else MessageBox.Show("Element nicht gefunden!", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error) End If
Listing 9
Zugriff auf Attribute eines Knotens
Häufig enthalten Knoten zusätzliche Informationen, die im selben Knoten angegeben werden (sogenannte Attribute):
<ID="1" Tags="Freund|Schulkollege">
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:
'VB6 Debug.Print objXml.selectSingleNode("/Adressen/Kontakt[Vorname='Max']").attributes.length
'VB.NET
Debug.Print (objXml.selectSingleNode("/Adressen/Kontakt[Vorname='Max']").attributes.Count)
Listing 10
Über Angabe eines Index kann man auch auf ein bestimmtes Attribut zugreifen:
'VB6 Debug.Print objXml.selectSingleNode("/Adressen/Kontakt[1]").Attributes(0).text
'VB.NET
Debug.Print (objXml.selectSingleNode("/Adressen/Kontakt[1]").Attributes(0).Value)
Listing 11
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:
'VB6 Debug.Print objXml.selectSingleNode("/Adressen/Kontakt[1]/@ID").text
'VB.NET
Debug.Print (objXml.selectSingleNode("/Adressen/Kontakt[1]/@ID").Value)
Listing 12
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:
'VB6 Debug.Print objXml.selectSingleNode("/Adressen/Kontakt[@ID='1']/Vorname").Text
'VB.NET
Debug.Print (objXml.selectSingleNode("/Adressen/Kontakt[@ID='1']/Vorname").InnerText)
Listing 13
Das nachfolgende Beispiel gibt die Namen aller Attribute des ersten Kontaktes sowie deren Wert aus:
'VB6 Dim oAttribute As IXMLDOMAttribute For Each oAttribute In objXML.SelectSingleNode("/Adressen/Kontakt[1]").Attributes Debug.Print oAttribute.nodeName & ":" & oAttribute.Text Next
'VB.NET For Each oAttribute As Xml.XmlAttribute In objXML.SelectSingleNode("/Adressen/Kontakt[1]").Attributes Debug.Print(oAttribute.Name & ":" & oAttribute.Value) Next
Listing 14
Wie beim Zugriff auf Elemente ist es auch beim direkten Zugriff auf Attribute ratsam eine Überprüfung durchzuführen, ob ein passendes Attribut gefunden wurde:
'VB6 Dim oAttribute As IXMLDOMAttribute Set oAttribute = objXML.SelectSingleNode("/Adressen/Kontakt[1]/@Klasse") If Not oAttribute Is Nothing Then Debug.Print oAttribute.Text Else MsgBox "Attribut nicht gefunden!", vbCritical, "Fehler" End If
'VB.NET Dim oAttribute As Xml.XmlAttribute = objXML.SelectSingleNode("/Adressen/Kontakt[1]/@Klasse") If Not oAttribute Is Nothing Then Debug.Print(oAttribute.Value) Else MessageBox.Show("Element nicht gefunden!", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error) End If
Listing 15
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 ausgegeben werden. Dies wird über die Methode selectNodes realisiert.
'VB6 Dim einKontakt As IXMLDOMNode For Each einKontakt In objXML.SelectNodes("/Adressen/Kontakt") Debug.Print einKontakt.Text Next
'VB.NET For Each einKontakt As Xml.XmlNode In objXML.SelectNodes("/Adressen/Kontakt") Debug.Print(einKontakt.InnerText) Next
Listing 16
Natürlich besteht auch die Möglichkeit, nur Elemente mit bestimmten Attributen aufzulisten (hier etwa das Element mit der ID "1")
'VB6 Dim alleKontakte As IXMLDOMNodeList Dim einKontakt As IXMLDOMElement Set alleKontakte = objXML.selectNodes("/Adressen/Kontakt[@ID='1']") For Each einKontakt In alleKontakte Debug.Print einKontakt.Text Next
'VB.NET Dim alleKontakte As xml.XmlNodeList= objXML.SelectNodes("/Adressen/Kontakt[@ID='1']") For Each einKontakt As Xml.XmlNode In alleKontakte Debug.Print(einKontakt.InnerText) Next
Listing 17
Oder noch etwas herrausfordernder: Alle Kontakte mit dem Tag "Freund" (in VB6 muss 'echtes XPath' aktiviert sein! siehe Listing 2):
'VB6 Dim alleKontakte As IXMLDOMNodeList Dim einKontakt As IXMLDOMElement Set alleKontakte = objXML.selectNodes("/Adressen/Kontakt[contains(concat('|', @Tags, '|'), '|Freund|')]") For Each einKontakt In alleKontakte Debug.Print einKontakt.Text Next
'VB.NET Dim alleKontakte As Xml.XmlNodeList = objXML.SelectNodes("/Adressen/Kontakt[contains(concat('|', @Tags, '|'), '|Freund|')]") For Each einKontakt As Xml.XmlNode In alleKontakte Debug.Print(einKontakt.InnerText) Next
Listing 18
Erstellen von XML Dateien
Über das DOM Objektmodell lassen sich XML Strukturen natürlich auch erstellen. Hierbei kümmert sich das Objekt auch um die korrekte Codierung der Daten.
'VB6 Option Explicit Dim objXML As MSXML2.DOMDocument40 Private Sub Form_Load() Dim oKontaktNode As IXMLDOMElement Set objXML = New MSXML2.DOMDocument 'Meta Informationen einfügen objXML.InsertBefore objXML.createProcessingInstruction("xml", "version='1.0' encoding='windows-1252'"), objXML.DocumentElement 'Adressen Knoten einfügen objXML.appendChild objXML.createElement("Adressen") 'einen Kontakt unterhalb von Adressen anlegen Set oKontaktNode = objXML.SelectSingleNode("Adressen").appendChild(objXML.createElement("Kontakt")) 'Kontaktdaten anlegen With oKontaktNode .setAttribute "ID", "1" .setAttribute "Tags", "Gruppe1" .appendChild(objXML.createElement("Vorname")).Text = "José & Maria" .appendChild(objXML.createElement("Name")).Text = "Sárensaò" End With 'Speichern objXML.Save App.Path & "\demo2.xml" End Sub
'VB.NET Public Class Form1 Public objXML As Xml.XmlDocument Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load objXML = New Xml.XmlDocument 'Meta Informationen einfügen objXML.InsertBefore(objXML.CreateXmlDeclaration("1.0", "windows-1252", Nothing), objXML.DocumentElement) 'Adressen Knoten einfügen objXML.AppendChild(objXML.CreateElement("Adressen")) 'einen Kontakt unterhalb von Adressen anlegen Dim oKontaktNode As Xml.XmlElement = objXML.SelectSingleNode("Adressen").AppendChild(objXML.CreateElement("Kontakt")) 'Kontaktdaten anlegen With oKontaktNode .SetAttribute("ID", "1") .SetAttribute("Tags", "Gruppe1") .AppendChild(objXML.CreateElement("Vorname")).InnerText = "José & Maria" .AppendChild(objXML.CreateElement("Name")).InnerText = "Sárensaò" End With 'Speichern objXML.Save(My.Application.Info.DirectoryPath & "\demo2.xml") End Sub End Class
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 2006
Daniel Aue 2013
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.