creating a recursive function to loop through sub menus in xml file using vb.net

I am trying to create a recursive loop to read  a xml file and add nodes to a treeview, I am having a hard time doing this.  Can anyone provide a link or a tutorial on xml that may help me using vb.net, or provide a code example?  I am not sure which is better using an xmlreader or loading it into an xmldocument. My xml is below.   I have searched the web a lot and found some solutions but I cant get it to work correctly with my xml file.  My main problem is that I dont know how to set up a child node under a correct parent node when the submenu element is read in.

<?xml version="1.0" encoding="utf-8" ?>
<menu>
      <menuItem>
            <text>Home</text>
            <url>MyHome.aspx</url>
      </menuItem>
      <menuItem>
             <text>Osha Standards</text>
             <submenu>
                  <menuItem>
                        <text>Osha Home</text>
                        <url>http://osha/home.html</url>
                  </menuItem>
                  <menuItem>
                        <text>Osha Rights</text>
                        <url>http://osha/rights.html</url>
                  </menuItem>
                  <menuItem>
                        <text>Osha Safety</text>
                        <url>http://osha/safety.html</url>
                  </menuItem>
            </submenu>
      </menuItem>
      <menuItem>
            <text>Old Safety</text>
            <url>http://Old_Safety.aspx</url>
      </menuItem>
</menu>
tentavariousAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

tentavariousAuthor Commented:
This is what I have so far, I am building an array, but it only adds one parent and one child for each text and url element.

 Sub buildviews(ByVal xmlfilehold As String, ByVal lview As TreeView)
        Dim xmlreader2 As New XmlTextReader(xmlfilehold)
        Dim sarray(2) As String
        Dim x As Integer = 0

        While xmlreader2.Read
            If xmlreader2.Name = "text" AndAlso xmlreader2.NodeType = XmlNodeType.Element Then 'check for string text
                sarray(x) = xmlreader2.ReadString
                x += 1
            End If
            If xmlreader2.Name = "url" AndAlso xmlreader2.NodeType = XmlNodeType.Element Then 'check for url text
                sarray(x) = xmlreader2.ReadString
                With lview.Nodes.Add(sarray(x - 1)).Nodes.Add(sarray(x))
                    .ImageIndex = 2
                    .SelectedImageIndex = 2
                End With
                x = 0
            End If
        End While
        xmlreader2.Close()
         End Sub
0
JRossi1Commented:
How about looping through a dataset based on the xml submenu?

menuDS.ReadXML("submenu.xml")

Then you can do something like this:

foreach (DataTable dt in menuDS.Tables)
<<< code >>>

        foreach (DataRow dr in menuDS.Tables[0].Rows)
                  <<<<<  Code >>>>>
         next
next


0
tentavariousAuthor Commented:
Could you give me example using my xml, how to i handle the submenus?
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

JRossi1Commented:
I didn't realize that you were attempting to load the file into a TreeView....  Here is code that I use to load an xml file into a treeview:

' Load a TreeView control from an XML file.
Private Sub LoadTreeViewFromXmlFile(ByVal file_name As _
    String, ByVal trv As TreeView)
    ' Load the XML document.
    Dim xml_doc As New XmlDocument
    xml_doc.Load(file_name)

    ' Add the root node's children to the TreeView.
    trv.Nodes.Clear()
    AddTreeViewChildNodes(trv.Nodes, _
        xml_doc.DocumentElement)
End Sub

' Add the children of this XML node
' to this child nodes collection.
Private Sub AddTreeViewChildNodes(ByVal parent_nodes As _
    TreeNodeCollection, ByVal xml_node As XmlNode)
    For Each child_node As XmlNode In xml_node.ChildNodes
        ' Make the new TreeView node.
        Dim new_node As TreeNode = _
            parent_nodes.Add(child_node.Name)

        ' Recursively make this node's descendants.
        AddTreeViewChildNodes(new_node.Nodes, child_node)

        ' If this is a leaf node, make sure it's visible.
        If new_node.Nodes.Count = 0 Then _
            new_node.EnsureVisible()
    Next child_node
End Sub

0
tentavariousAuthor Commented:
I tried using the exact code and it doesnt work with the xml file i have.  
0
tentavariousAuthor Commented:
My main problem is I cant get the submenu to break out correctly and the <url> tag should branch from the <text> tag not be its own branch.
0
JRossi1Commented:
I'm not exactly sure how to break out the url tag so perhaps, to make things simpler, you can put the url tag next to the text

<text>Osha Home - http://osha/home.html</text>

Just a thought.
0
tentavariousAuthor Commented:
Still not showing up correctly here is my new xml

<?xml version="1.0" encoding="utf-8" ?>
<menu>
     <menuItem>
          <text>Home - MyHome.aspx</text>
     </menuItem>
     <menuItem>
           <text>Osha Standards</text>
           <submenu>
               <menuItem>
                    <text>Osha Home - http://osha/home.html</text>
               </menuItem>
               <menuItem>
                    <text>Osha Rights - http://osha/rights.html</text>
               </menuItem>
               <menuItem>
                    <text>Osha Safety - http://osha/safety.html</text>
               </menuItem>
          </submenu>
     </menuItem>
     <menuItem>
          <text>Old Safety - http://Old_Safety.aspx</text>
     </menuItem>
</menu>

Using your code with the recursive loop here is exactly what my tree looks like
menuItem
     text
      #text
menuItem
     text
      #text
     submenu
      menuItem
          text
             #text      
      menuItem
          text
             #text      
        menuItem
          text
             #text      
menuItem
     text
      #text
      
0
prakash_prkCommented:
Try this functions

Regards
Prakash
----------------------------------------------------------------------------------------------------------------------------------------
 Private Sub LoadTreeView()
        Dim xmlContent As String

        Dim sReader As New StreamReader("I:\Temp\tt.xml")
        xmlContent = sReader.ReadToEnd()
        sReader.Close()

        FileTreeViewWithMenus(TreeView1.Nodes, xmlContent)

    End Sub

    Private Sub FileTreeViewWithMenus(ByVal treeViewNodes As TreeNodeCollection, ByVal xmlContent As String)
        treeViewNodes.Clear()

        Dim treeviewNode As TreeNode
        Dim xmlDocument As New XmlDocument

        xmlDocument.LoadXml(xmlContent)

        Dim menuItems As XmlNodeList = xmlDocument.SelectNodes("//menu/menuItem")

        For Each menuItem As XmlElement In menuItems
            treeviewNode = New TreeNode
            PopulateMenu(menuItem, treeviewNode)
            treeViewNodes.Add(treeviewNode)
        Next

    End Sub

    Private Sub PopulateMenu(ByVal menuItem As XmlElement, ByVal treeviewNode As TreeNode)

        Dim textValue As String = menuItem("text").InnerText

        Dim startHipenIndex As Integer = textValue.IndexOf("-")


        If (startHipenIndex <> -1) Then
            treeviewNode.Tag = textValue.Substring(startHipenIndex).Trim()
            treeviewNode.Text = textValue.Substring(0, startHipenIndex).Trim()
        Else
            treeviewNode.Tag = String.Empty
            treeviewNode.Text = textValue.Trim()
        End If

        If (Not menuItem("submenu") Is Nothing) Then
            Dim childNode As TreeNode
            For Each childMenuItm As XmlElement In menuItem("submenu").ChildNodes
                childNode = New TreeNode
                PopulateMenu(childMenuItm, childNode)
                treeviewNode.Nodes.Add(childNode)
            Next
        End If
    End Sub

    Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
        Dim msg As String
        msg = "Selected Node :" & e.Node.Text & vbCrLf
        msg &= "Selected Value :" & e.Node.Tag.ToString
        MsgBox(msg)
    End Sub
----------------------------------------------------------------------------------------------------------------------------------------
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
tentavariousAuthor Commented:
Hey Prakash, I think you pretty much solved my other question as well, I just have two problems, how do i change the image index and if there isnt a <url></url> tag i get this error:  The data at the root level is invalid.  Not all my nodes will contain a hyperlink some will just be a menu that when click will display its sub menus.
0
prakash_prkCommented:
hi tentavarious

I does not saw the original xml format. I had given code for the format u specified later.
Your original XML format is more appropriate than u proposed later.

please use the format you first specified
change the "PopulateMenu" function with the following code
----------------------------------------------------------------------------------
if( not menuItem("url") is nothing ) then
  treeviewNode.Tag = menuItem("url").InnerText
else
 treeviewNode.Tag = string.empty
end if

treeviewNode.Text = menuItem("text").InnerText
----------------------------------------------------------------------------------

Thank you

Regards
Prakash
0
tentavariousAuthor Commented:
So replace this :
treeviewNode.Tag = menuItem("url").InnerText
        treeviewNode.Text = menuItem("text").InnerText
        If (Not menuItem("subMenu") Is Nothing) Then
            Dim childNode As TreeNode
            For Each childMenuItm As XmlElement In menuItem("subMenu").ChildNodes
                childNode = New TreeNode
                PopulateMenu(childMenuItm, childNode)
                treeviewNode.Nodes.Add(childNode)
            Next
        End If
   
with this:
    If (Not menuItem("url") Is Nothing) Then
            treeviewNode.Tag = menuItem("url").InnerText
        Else
            treeviewNode.Tag = String.Empty
        End If

        treeviewNode.Text = menuItem("text").InnerText

I did that and now my submenus dont show up
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.