Attribut von XML wird nicht gelesen


joshi123

Grünschnabel
Hallo,

leider habe ich im Forum nicht das richtige gefunden, bzw. konnte mit den Threads dann nichts anfangen um mein Problem zu lösen ;-|

Ich habe das Problem, dass mein VB-Code nicht alle Attribute von meiner XML ausliest.

Hier erst mal die Codes :
XML :
XML:
<?xml version="1.0" encoding="UTF-8"?>
<Programme Path="1">
  <Feld Icon="Folder.ico" Path="2">Feld 1<VisualStudio Path="C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe" Icon="VS.png">Visual Studio</VisualStudio>
    <Excel Path="C:\Program Files\Microsoft Office 15\root\office15\EXCEL.EXE" Icon="Excel.png">Excel</Excel>
  </Feld>
  <Home Icon="Folder.ico" Path="3">Home Place<Notepad Path="C:\Program Files\Notepad++\notepad++.exe" Icon="notepad.png">Notepad ++</Notepad>
    <JaTool Path="C:\Program Files (x86)\Tool7\javaw.exe" Argumente="-splash:splash.png -cp ./cl/cl.jar; -Dawt.useSystemAAFontSettings=on" Icon="JaTool.ico" RunPath="C:\Program Files (x86)\Tool7\bin\..">JaTool</JaTool>
  </Home>
</Programme>

VB-Code :
Code:
Option Strict On
Imports System.Xml
Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions
Public Class treeViewLoadXml
    Dim imgLst As New ImageList
    Dim vImgPath(-1) As String, iv As Int32 = 0
    Private Sub treeViewLoadXml_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Load_XML()
    End Sub
    Public Sub Load_XML()
        Try
            ' Get Xml's file stream.
            imgLst.ImageSize = New Drawing.Size(30, 27)
            Dim vPath() As String = Split(Application.ExecutablePath, "\")
            vPath(vPath.Length - 1) = "XMLFile1.xml"
            Dim filepath As String = Join(vPath, "\")
            Dim _rstream As New FileStream(filepath, FileMode.Open)
            ' Load Xml document.
            '
            Dim dom As New XmlDocument()
            dom.Load(_rstream)
            _rstream.Close()
            ' Initialize treeView control.
            '
            TreeView1.BeginUpdate()
            TreeView1.Nodes.Clear()
            TreeView1.Nodes.Add(New TreeNode(dom.DocumentElement.Name))
            ' Populate the treeView with the dom nodes.
            '
            AddNode(dom.DocumentElement, TreeView1.Nodes(0))
            If CBool(iv) Then
                For i = 0 To iv - 1
                    imgLst.Images.Add(Image.FromFile(vImgPath(i)))
                Next
                TreeView1.ImageList = imgLst
            End If
            TreeView1.EndUpdate()
            'TreeView1.ExpandAll()
        Catch xmlEx As XmlException
            MessageBox.Show(xmlEx.Message)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub
    Private Sub AddNode(ByVal inXmlNode As XmlNode, ByVal inTreeNode As TreeNode)
        Dim i As Integer
        If inXmlNode.HasChildNodes Then
            Dim nodeList As XmlNodeList
            nodeList = inXmlNode.ChildNodes
            i = 0
            While i <= nodeList.Count - 1
                Dim xNode As XmlNode = inXmlNode.ChildNodes(i)
                Dim imgIndex As Int32 = -1
                Dim SelimgIndex As Int32 = -1
                If xNode.Attributes IsNot Nothing Then
                    For Each att As XmlAttribute In xNode.Attributes
                        If att.Name = "Icon" Then
                            imgIndex = addImage(att.Value)
                            SelimgIndex = addImage(att.Value)
                            Exit For
                        End If
                    Next
                End If
                Dim tNode As New TreeNode(xNode.Name)
                Dim bIsTxt As Boolean = False
                If tNode.Text = "#text" Then
                    tNode.Text = xNode.Value
                    bIsTxt = True
                End If
                If imgIndex <> -1 Then
                    tNode.ImageIndex = imgIndex
                End If
                If SelimgIndex <> -1 Then
                    tNode.SelectedImageIndex = SelimgIndex
                End If
                If bIsTxt Then
                    'inTreeNode.Text += " " + tNode.Text '
                    inTreeNode.Text = tNode.Text
                Else
                    inTreeNode.Nodes.Add(tNode)
                    AddNode(xNode, tNode)
                End If
                i += 1
            End While
            If inXmlNode.Attributes IsNot Nothing AndAlso inXmlNode.Attributes("Path") IsNot Nothing Then
                inTreeNode.Name = inXmlNode.Attributes("Path").Value
            End If
            If inXmlNode.Attributes IsNot Nothing AndAlso inXmlNode.Attributes("Argumente") IsNot Nothing Then
                inTreeNode.Name = inXmlNode.Attributes("Argumente").Value
            End If
            If inXmlNode.Attributes IsNot Nothing AndAlso inXmlNode.Attributes("RunPath") IsNot Nothing Then
                inTreeNode.Name = inXmlNode.Attributes("RunPath").Value
            End If
        End If
    End Sub
    Function addImage(path As String) As Int32
        Dim i As Int32 = Array.IndexOf(vImgPath, path)
        If i = -1 AndAlso IO.File.Exists(path) Then
            ReDim Preserve vImgPath(iv)
            Me.vImgPath(iv) = path
            i = iv
            iv += 1
        End If
        Return i
    End Function
    Private Sub TreeView1_NodeMouseDoubleClick(sender As Object, e As System.Windows.Forms.TreeNodeMouseClickEventArgs) Handles TreeView1.NodeMouseDoubleClick
        Try
            Dim Path As String = TreeView1.SelectedNode.Name
            Dim Argumente As String = TreeView1.SelectedNode.Name
            Dim RunPath As String = TreeView1.SelectedNode.Name

            If IsNumeric(Path) Then
                Dim nAction As Int32 = Int32.Parse(Path)
                Select Case nAction
                    Case 1 'wenn was gemacht werden soll, wenn Path ist nur eine Zahl
                        ' do job for Path="1" ' 
                    Case 2
                        ' do job for Path="2" '
                    Case 3
                        ' do job for Path="3" '
                End Select
            Else
                Select Case e.Node.Text
                    Case "Visual Studio"
                        MsgBox("Visual Studio")
                        '...
                    Case "Excel"
                        MsgBox("Excel")
                        '...
                    Case "Notepad ++"
                        MsgBox("Notepad")
                        '...
                End Select
                If File.Exists(Path) Then
                    Process.Start(Path)
                    'Dim MyProcess As New Process()
                    'MyProcess.StartInfo.FileName = Path
                    'MyProcess.StartInfo.Arguments = Argumente
                    'MyProcess.Start()
                End If
            End If
        Catch ex As Exception
            MsgBox("kein Programm gefunden")
        End Try
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim Path As String = TreeView1.SelectedNode.Name
        Dim Argumente As String = TreeView1.SelectedNode.Name
        Dim RunPath As String = TreeView1.SelectedNode.Name
        Label1.Text = Path
        Label2.Text = Argumente
        Label3.Text = RunPath
       
    End Sub
End Class

Die XML wird soweit gelesen, dass jeder Knoten sein Icon bekommt ("Icon" welches als Attribut angegeben ist) und auch der Pfad (Path) zum starten des Programms wird gelesen. Jedoch werden die weiteren Attribute ("Argumente" und "RunPath") nicht mit eingelesen und können somit auch nicht von mir verwendet werden.

Ich komme einfach nicht weiter und hoffe das ihr mir hier weiterhelfen könnt!?!?
 

Spyke

Premium-User
Setzt mal Breakpoint bei Argumente und RunPath ob dort reignesprungen wird.
Meine erste vermutung wäre erstmal das die Arguemnte richtig abgefragt werden aber da du mit dem gleichen inTreeNode Arbeitest und dort den Namen immer neu setzt, gewinnt das letzte Xml-Argumente das abgefragt wird.
Würd ich jetzt auf den ersten Blick vermuten.
 

joshi123

Grünschnabel
Guter Tipp mit den Breakpoints.
Es ist tatsächlich so, dass es egal ist, ob ich die Attribute separat definiere (per "Dim Argumente As String = TreeView1.SelectedNode.Name"), es wird immer das letzte Attribut von dem Knoten ausgegeben.
Nun ist mein Latein zu Ende und ich komm nicht mehr weiter.
 

joshi123

Grünschnabel
Ich hänge leider weiterhin fest. ich weiss nicht, wie ich diese Hilfsklasse nun in meinen Code einbauen soll, damit es so funktioniert, wie es soll ;-( dafür bin ich einfach noch ein Grünschnabel
 

Spyke

Premium-User
Hilfsklasse:
Code:
class MeineKlasse
{
    public string EigenschaftA { get; set; }
    public string EigenschaftB { get; set; }
}

Werte zuweisen:
Code:
MeineKlasse mk = new MeineKlasse();
...
mk.EigenschaftA = inXmlNode.Attributes["Path"].Value;
...
mk.EigenschaftB = inXmlNode.Attributes["RunPath"].Value;
...
inTreeNode.Tag = mk;

Tag abfragen:
Code:
MeineKlasse mk = TreeView1.SelectedNode.Tag as MeineKlasse;
if (mk != null)
{
    ....
}

ist zwar C# aber vielleicht hilfts bissl
 

joshi123

Grünschnabel
Komplett umwandeln und verstehen kann ich es leider nicht.
Mein Versuch :
Hilfsklasse
Code:
Public Class MeineKlasse
        Dim EigenschaftA As String
        Dim EigenschaftB As String
    End Class

bei Werte zuweisen und Tag abfragen kriselt es leider schon... Das was ich in VB übersetzen konnte, müsste folgendes sein :
Code:
mk.EigenschaftA = inXmlNode.Attributes("Path").Value
            ...
        mk.EigenschaftB = inXmlNode.Attributes("RunPath").Value


inTreeNode.Tag = mk

        MeineKlasse.mk = TreeView1.SelectedNode.Tag as MeineKlasse
        If mk IsNot Nothing Then
            '...
        End If
 

joshi123

Grünschnabel
habe folgendes jetzt alles probiert.

Code:
Dim MeineKlasse MK As New MeineKlasse() = TryCast()
        inTreeNode.Tag = mk

        MeineKlasse.mk = TreeView1.SelectedNode.Tag as MeineKlasse

alles ohne Erfolg.

Danke für die Mühen, aber ich glaube ich muss das alles irgendwie doch ohne XML umsetzen ;-( Mir fehlen dazu einfach zu viele Kenntnisse.
Vielleicht kann noch wer mit VB.net noch helfen irgendwann!?
 

Spyke

Premium-User
Tag auslesen (Vorausgesetzt du hast im Tag der Node auch ein Objekt vom Typ MeineKlasse hinterlegt):
Code:
Dim mk As MeineKlasse = TryCast(TreeView1.SelectedNode.Tag, MeineKlasse)
If mk Is Nothing Then
...
Else
...
End If
 

joshi123

Grünschnabel
Ich vermute, dass mit "Tag" das Attribut von den jeweils ausgewählten Knoten sein soll!?
So wie ich es verstanden habe, sieht der Code nun wie folgt aus. Das Problem ist jedoch, dass ich die Labels nicht mit den Daten der Attribute ("RunPath" und "Argumente") ausgeben lassen kann. RunPath und Argumente wird mir hier als Fehler angezeigt, weil sie ein "TYP" sind!?!? Das obwohl "RunPath" und "Argumente" global als String definiert wurde?!?

Code:
Public Class RunPath
        Dim RunPath As String
    End Class
    Public Class Argumente
        Dim Argumente As String
    End Class
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        Dim mk As RunPath = TryCast(TreeView1.SelectedNode.Tag, RunPath)
        If mk IsNot Nothing Then
            Label1.Text = RunPath
        End If
        Dim mk1 As Argumente = TryCast(TreeView1.SelectedNode.Tag, Argumente)
        If mk1 IsNot Nothing Then
            Label2.Text = Argumente
        End If
    End Sub

Vielleicht nochmal zur genaueren Erklärung :
Auf meiner Form1 habe ich einen XMLTreeView, welchen ich mit den Daten der XML-Datei befülle. Aktuell sollte es eigentlich so sein, dass wenn ich den Knoten "JaTool" ausgewählt habe und dann auf den Button-3 klicke, dann soll das Label1 und Label2 mit den jeweiligen Daten der Attribute aus der XML befüllt werden.
 

Spyke

Premium-User
eine Klasse Machen die alle deine Xml Attribute für eine XmlNode hält, z.B.:
Code:
Public Class MeineXmlWerte
        Dim RunPath As String
        Dim Argumente As String
End Class

auslesen des tags einer selektierten TreeView Node und Label setzen:
Code:
  Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        Dim mk As MeineXmlWerte = TryCast(TreeView1.SelectedNode.Tag, MeineXmlWerte)
        If mk IsNot Nothing Then
            Label1.Text = mk.RunPath
            Label2.Text = mk.Argumente
        End If
    End Sub


P.S.: jetzt muss nur noch der Tag richtig gesetzt/angegeben werden
 

joshi123

Grünschnabel
Danke. Nur leider bleibt es dabei, dass es "mk.RunPath" und "mk.Argumente" als Fehler definiert - diesmal jedoch :
Fehler 1 "WindowsApplication1.treeViewLoadXml.MeineXmlWerte.RunPath" ist in diesem Kontext nicht zugreifbar, da es "Private" ist.
Fehler 2 "WindowsApplication1.treeViewLoadXml.MeineXmlWerte.Argumente" ist in diesem Kontext nicht zugreifbar, da es "Private" ist.
 

joshi123

Grünschnabel
Der Fehler war, anstatt "Public RunPath As String" hatte ich "Dim RunPath As String".

So nun ist der Code ohne Fehler, jedoch bleibt es dabei, die Labels nicht mit den Daten gefüllt werden, welche in den Attributen bei der XML stehen... Es kommt aber auch keine Fehlermeldung oder Exception.

Hier nochmal der komplette Code :
Code:
Option Strict On
Imports System.Xml
Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions
Public Class treeViewLoadXml
    Dim imgLst As New ImageList
    Dim vImgPath(-1) As String, iv As Int32 = 0
    Private Sub treeViewLoadXml_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Load_XML()
    End Sub
    Public Sub Load_XML()
        Try
            ' Get Xml's file stream.
            imgLst.ImageSize = New Drawing.Size(30, 27)
            Dim vPath() As String = Split(Application.ExecutablePath, "\")
            vPath(vPath.Length - 1) = "XMLFile1.xml"
            Dim filepath As String = Join(vPath, "\")
            Dim _rstream As New FileStream(filepath, FileMode.Open)
            ' Load Xml document.
            '
            Dim dom As New XmlDocument()
            dom.Load(_rstream)
            _rstream.Close()
            ' Initialize treeView control.
            '
            TreeView1.BeginUpdate()
            TreeView1.Nodes.Clear()
            TreeView1.Nodes.Add(New TreeNode(dom.DocumentElement.Name))
            ' Populate the treeView with the dom nodes.
            '
            AddNode(dom.DocumentElement, TreeView1.Nodes(0))
            If CBool(iv) Then
                For i = 0 To iv - 1
                    imgLst.Images.Add(Image.FromFile(vImgPath(i)))
                Next
                TreeView1.ImageList = imgLst
            End If
            TreeView1.EndUpdate()
            'TreeView1.ExpandAll()
        Catch xmlEx As XmlException
            MessageBox.Show(xmlEx.Message)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

    Private Sub AddNode(ByVal inXmlNode As XmlNode, ByVal inTreeNode As TreeNode)
        Dim i As Integer
        If inXmlNode.HasChildNodes Then
            Dim nodeList As XmlNodeList
            nodeList = inXmlNode.ChildNodes
            i = 0
            While i <= nodeList.Count - 1
                Dim xNode As XmlNode = inXmlNode.ChildNodes(i)
                Dim imgIndex As Int32 = -1
                Dim SelimgIndex As Int32 = -1
                If xNode.Attributes IsNot Nothing Then
                    For Each att As XmlAttribute In xNode.Attributes
                        If att.Name = "Icon" Then
                            imgIndex = addImage(att.Value)
                            SelimgIndex = addImage(att.Value)
                            Exit For
                        End If
                    Next
                End If
                Dim tNode As New TreeNode(xNode.Name)
                Dim bIsTxt As Boolean = False
                If tNode.Text = "#text" Then
                    tNode.Text = xNode.Value
                    bIsTxt = True
                End If
                If imgIndex <> -1 Then
                    tNode.ImageIndex = imgIndex
                End If
                If SelimgIndex <> -1 Then
                    tNode.SelectedImageIndex = SelimgIndex
                End If
                If bIsTxt Then
                    'inTreeNode.Text += " " + tNode.Text '
                    inTreeNode.Text = tNode.Text
                Else
                    inTreeNode.Nodes.Add(tNode)
                    AddNode(xNode, tNode)
                End If
                i += 1
            End While
            If inXmlNode.Attributes IsNot Nothing AndAlso inXmlNode.Attributes("Path") IsNot Nothing Then
                inTreeNode.Name = inXmlNode.Attributes("Path").Value
            End If
            If inXmlNode.Attributes IsNot Nothing AndAlso inXmlNode.Attributes("RunPath") IsNot Nothing Then
                inTreeNode.Name = inXmlNode.Attributes("RunPath").Value
            End If
            If inXmlNode.Attributes IsNot Nothing AndAlso inXmlNode.Attributes("Argumente") IsNot Nothing Then
                inTreeNode.Name = inXmlNode.Attributes("Argumente").Value
            End If
        End If

    End Sub
   

    Function addImage(path As String) As Int32
        Dim i As Int32 = Array.IndexOf(vImgPath, path)
        If i = -1 AndAlso IO.File.Exists(path) Then
            ReDim Preserve vImgPath(iv)
            Me.vImgPath(iv) = path
            i = iv
            iv += 1
        End If
        Return i
    End Function
    Private Sub TreeView1_NodeMouseDoubleClick(sender As Object, e As System.Windows.Forms.TreeNodeMouseClickEventArgs) Handles TreeView1.NodeMouseDoubleClick
        Try
            Dim Path As String = TreeView1.SelectedNode.Name
            Dim Argumente As String = TreeView1.SelectedNode.Name
            Dim RunPath As String = TreeView1.SelectedNode.Name

            If IsNumeric(Path) Then
                Dim nAction As Int32 = Int32.Parse(Path)
                Select Case nAction
                    Case 1 'wenn was gemacht werden soll, wenn Path ist nur eine Zahl
                        ' do job for Path="1" ' 
                    Case 2
                        ' do job for Path="2" '
                    Case 3
                        ' do job for Path="3" '
                End Select
            Else
                Select Case e.Node.Text
                    Case "Visual Studio"
                        MsgBox("Visual Studio")
                        '...
                    Case "Excel"
                        MsgBox("Excel")
                        '...
                    Case "Notepad ++"
                        MsgBox("Notepad")
                        '...
                End Select
                If File.Exists(Path) Then
                    Process.Start(Path)
                End If
            End If
        Catch ex As Exception
            MsgBox("kein Programm gefunden")
        End Try
    End Sub

    Public Class MeineXmlWerte
        Public RunPath As String
        Public Argumente As String
    End Class
   
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        Dim mk As MeineXmlWerte = TryCast(TreeView1.SelectedNode.Tag, MeineXmlWerte)
        If mk IsNot Nothing Then
            Label1.Text = mk.RunPath
            Label2.Text = mk.Argumente
        End If
    End Sub
End Class
 

Spyke

Premium-User
du erstellst auch keine Instanz von MeineXmlWerte, setzt dort nicht die Werte und übergibst es auch nicht an das Tag der TreeView Node.

so ungefähr könnts/sollts sein
Code:
    Private Sub AddNode(ByVal inXmlNode As XmlNode, ByVal inTreeNode As TreeNode)


Dim mk As MeineXmlWerte = New MeineXmlWerte()
inTreeNode.Tag = mk


        Dim i As Integer
        If inXmlNode.HasChildNodes Then

...


            If inXmlNode.Attributes IsNot Nothing AndAlso inXmlNode.Attributes("RunPath") IsNot Nothing Then
                mk.RunPath = inXmlNode.Attributes("RunPath").Value
            End If
            If inXmlNode.Attributes IsNot Nothing AndAlso inXmlNode.Attributes("Argumente") IsNot Nothing Then
                mk.Argumente = inXmlNode.Attributes("Argumente").Value
            End If


...


    End Sub

Schau dir am besten mal an VB.Net Tutorial zu Klassen und deren Verwendung an.