Die Community zu .NET und Classic VB.
Menü

Tipp-Upload: VB.NET 0149: XPath-Ausdrücke verwenden

 von 

Hinweis zum Tippvorschlag  

Dieser Vorschlag wurde noch nicht auf Sinn und Inhalt überprüft und die Zip-Datei wurde noch nicht auf schädlichen Inhalt hin untersucht.
Bitte haben Sie ein wenig Geduld, bis die Freigabe erfolgt.

Über den Tipp  

Dieser Tippvorschlag ist noch unbewertet.

Der Vorschlag ist in den folgenden Kategorien zu finden:

  • Datenbanken und XML
  • Sonstiges

Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
XPath,xml

Der Vorschlag wurde erstellt am: 22.11.2007 18:34.
Die letzte Aktualisierung erfolgte am 27.01.2009 18:26.

Zurück zur Übersicht

Beschreibung  

Hier 8 Beispiele, wie man mit XPath-Ausdrücken einer Xml-Datei nahezu jede Information entreißen kann - und zwar jeweils mit einem 3-Zeiler.
Untersucht wird einfach die Kopie der ProjektDatei dieses Projektes.
Die ausgeführten Abfragen lassen sich sicherlich wesentlich optimieren, etwa durch Verwendung von XPathDocument und XPathIterator.

Der Tipp soll nur Appetit machen auf eine systematischere Auseinandersetzung mit der Abfragesprache "XPath"

MSDN fand ich wenig hilfreich, aber die W3Schools:
http://www.w3schools.com/xpath/default.asp

Hier kann dieser Tippvorschlag diskutiert werden:
http://foren.activevb.de/cgi-bin/foren/view.pl?forum=13&root=1471&msg=1471

Schwierigkeitsgrad

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

Download:

Download des Beispielprojektes [16,56 KB]

' Dieser Source stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!
'
' Beachten Sie, das vom Designer generierter Code hier ausgeblendet wird.
' In den Zip-Dateien ist er jedoch zu finden.

' ----------- Anfang Projektgruppe XPathSample.sln -----------
' ---------- Anfang Projektdatei XPathSample.vbproj ----------
' -------------- Anfang Datei frmXPathSample.vb --------------
' IDE-Voreinstellungen:
' Option Explicit On
' Option Strict On

' Project-Einstellungen:
' Imports Microsoft.VisualBasic.ControlChars
' Imports System.Windows.Forms

Imports System.Xml
Imports System.IO

Public Class frmXPathSample

    Private Enum QueryEnum
        CompileElement = 1
        CompileIncludeAttribute
        CompileIncludeAttribute2
        DefaultProperties
        AssemblyName
        OptionStrict
        UpdateStuff
        EckardsSpecial
    End Enum

    Private _XDoc As New XmlDocument

    Public Sub New()

        InitializeComponent()

        ' auch vllt. interessant: Listbox dynamisch mit Enums befüllen.
        ' So ist sie immer genau auf die im Code verwendbaren Optionen abgestimmt
        Me.ListBox1.DataSource = [Enum].GetValues(GetType(QueryEnum))
        _XDoc.Load(Path.Combine(Application.StartupPath, "XPathSample.vbproj"))

    End Sub

    Private Sub btQuery_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btQuery.Click

        Dim NspMngr As New XmlNamespaceManager(_XDoc.NameTable)

        ' Falls ein Default-Namespace vorhanden: denselben dem XmlNamespaceManager bekanntmachen,
        ' unter beliebigem Präfix
        NspMngr.AddNamespace("def", _XDoc.DocumentElement.NamespaceURI)

        Dim SB As New System.Text.StringBuilder
        Dim sXPath As String = ""
        Dim QueryType As QueryEnum = DirectCast(Me.ListBox1.SelectedItem, QueryEnum)

        Select Case QueryType

            Case QueryEnum.CompileElement

                ' Für XmlElemente ist ggfs. der Namespace anzugeben (hier: Default)
                sXPath = "def:Project/def:ItemGroup/def:Compile"

                Dim Nodes As XmlNodeList = _XDoc.SelectNodes(sXPath, NspMngr)

                For Each Xel As XmlElement In Nodes
                    SB.Append(Xel.OuterXml & Lf & Lf)
                Next

            Case QueryEnum.CompileIncludeAttribute

                ' "//" ist eine Art Wildcard für alle Ebenen - returnt dieselbe Nodelist wie vorher
                For Each Xel As XmlElement In _XDoc.SelectNodes("//def:Compile", NspMngr)

                    ' Ausgabe: greift den "Include"-Attribut-Wert heraus (also die Namen zu
                    ' kompilierender Dateien)
                    SB.Append(Xel.GetAttribute("Include") & Lf)
                Next

                ' -------- Ausgabe: ---------
                ' frmXPathSample.vb
                ' frmXPathSample.Designer.vb
                ' My Project\AssemblyInfo.vb
                ' My Project\Application.Designer.vb
                ' My Project\Resources.Designer.vb
                ' My Project\Settings.Designer.vb

            Case QueryEnum.CompileIncludeAttribute2

                ' Diese Query returnt gleich nur die Attribute-Nodes
                sXPath = "//def:Compile/@Include"

                For Each XAttr As XmlAttribute In _XDoc.SelectNodes(sXPath, NspMngr)
                    SB.Append(XAttr.Value & Lf)
                Next

            Case QueryEnum.DefaultProperties

                ' anspruchsvollere XPath-Abfrage:
                ' alle XmlElemente einer PropertyGroup, die kein Condition-Attribut hat
                sXPath = "//def:PropertyGroup[not(@Condition)]/*"

                For Each Xel As XmlElement In _XDoc.SelectNodes(sXPath, NspMngr)

                    ' kultivierte Darstellung: Nodename + Innertext
                    SB.Append(String.Concat(Xel.Name, Tab, ": ", Xel.InnerText, Lf))
                Next

            Case QueryEnum.AssemblyName
                sXPath = "//def:PropertyGroup[not(@Condition)]/def:AssemblyName/text()"

                ' DirectCast zeigt, daß ein XmlText returnt
                Dim Nd As XmlText = DirectCast(_XDoc.SelectSingleNode(sXPath, NspMngr), XmlText)

                SB.Append(Nd.OuterXml)

            Case QueryEnum.OptionStrict
                sXPath = "//def:PropertyGroup[not(@Condition)]/def:OptionStrict"

                With _XDoc.SelectSingleNode(sXPath, NspMngr)
                    SB.Append(String.Concat(.Name, ": ", .InnerText))
                End With

            Case QueryEnum.UpdateStuff

                ' anspruchsvollere XPath-Abfrage:
                ' alle XmlElemente der Default-PropertyGroup, deren Name mit 'Update' anfängt
                sXPath = "//def:PropertyGroup[not(@Condition)]/*[starts-with(name(),'Update')]"

                For Each Xel As XmlElement In _XDoc.SelectNodes(sXPath, NspMngr)
                    SB.Append(String.Concat(Xel.Name, Tab, ": ", Xel.InnerText, Lf))
                Next

            Case QueryEnum.EckardsSpecial

                ' Hier greifen wir mal auf einen anderen als den Default-Namespace zu.
                ' Der Prefix muß mit dem im XPath verwendeten übereinstimmen (kann abweichen von
                ' dem im Xml-File definierten). Der uri aber muß mit dem aus der Datei
                ' übereinstimmen.
                NspMngr.AddNamespace(prefix:="Spatzenkanonier", uri:="HiHaHiHaHu")

                ' alle Attribute
                sXPath = "def:Project/Spatzenkanonier:MyElement/@*"
                For Each XAttr As XmlAttribute In _XDoc.SelectNodes(sXPath, NspMngr)
                    SB.Append(String.Concat(XAttr.Name, Tab, ": ", XAttr.InnerText, Lf))
                Next

        End Select

        MsgBox(SB.ToString, Title:=QueryType.ToString)

    End Sub ' btQuery_Click

    Private Sub btOpenXDoc_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles btOpenXDoc.Click

        ' Der Dateiname steckt im XmlDocument drin, muß aber in Pfad-Syntax überführt werden
        With New Uri(_XDoc.BaseURI)
            System.Diagnostics.Process.Start("Notepad", .LocalPath)
        End With

    End Sub

    Private Sub btNamespaces_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles btNamespaces.Click

        DisplayNamespaces()

    End Sub

    Private Sub DisplayNamespaces()

        ' Over-coded - üblicherweise genügt es, das DocumentElement zu untersuchen
        Dim SB As New System.Text.StringBuilder

        SB.Append(String.Concat("   Prefix", Tab, Tab, "NamespaceUri", Lf, Lf))

        For Each Xel As XmlElement In _XDoc.SelectNodes("//*") ' alle(!) Elemente nachgucken
            For Each Attr As XmlAttribute In Xel.Attributes

                Dim AttrName As String = Attr.Name

                If AttrName.StartsWith("xmlns") Then

                    Dim Prefix As String = "(no pref)"

                    If AttrName.Length > 6 Then Prefix = AttrName.Substring(6)
                    SB.Append(String.Concat(Prefix, Tab, ": ", Attr.Value, Lf))
                End If

            Next
        Next

        MsgBox(SB.ToString, Title:="DisplayNamespaces")

        ' Den Default-Namespace erhält man noch einfacher:
        MsgBox(_XDoc.DocumentElement.NamespaceURI, Title:="Default-Namespace")

    End Sub

End Class

' --------------- Ende Datei frmXPathSample.vb ---------------
' ----------- Ende Projektdatei XPathSample.vbproj -----------
' ------------ Ende Projektgruppe XPathSample.sln ------------

	

Diskussion  

Diese Funktion ermöglicht es, Fragen, die die Veröffentlichung des Tipps betreffen, zu klären, oder Anregungen und Verbesserungsvorschläge einzubringen. Nach der Veröffentlichung des Tipps werden diese Beiträge nicht weiter verlinkt. Allgemeine Fragen zum Inhalt sollten daher hier nicht geklärt werden.

Um eine Diskussion eröffnen zu können, müssen sie angemeldet sein.