Die Community zu .NET und Classic VB.
Menü

XML-Dateien lesen mit Hilfe der Microsoft XML Library bzw mit dem .NET Xml.XmlDocument

 von 

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

Gute Anleitung - Fritzi 07.06.13 15:37 2 Antworten